| // Copyright 2023 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "cheriot/riscv_cheriot_vector_opm_instructions.h" |
| |
| #include <cstdint> |
| #include <functional> |
| #include <ios> |
| #include <type_traits> |
| |
| #include "absl/base/casts.h" |
| #include "absl/log/check.h" |
| #include "absl/strings/string_view.h" |
| #include "cheriot/test/riscv_cheriot_vector_instructions_test_base.h" |
| #include "googlemock/include/gmock/gmock.h" |
| #include "mpact/sim/generic/instruction.h" |
| |
| namespace { |
| |
| using Instruction = ::mpact::sim::generic::Instruction; |
| using ::mpact::sim::generic::WideType; |
| |
| using ::mpact::sim::cheriot::Vaadd; |
| using ::mpact::sim::cheriot::Vaaddu; |
| using ::mpact::sim::cheriot::Vasub; |
| using ::mpact::sim::cheriot::Vasubu; |
| using ::mpact::sim::cheriot::Vdiv; |
| using ::mpact::sim::cheriot::Vdivu; |
| using ::mpact::sim::cheriot::Vmacc; |
| using ::mpact::sim::cheriot::Vmadd; |
| using ::mpact::sim::cheriot::Vmand; |
| using ::mpact::sim::cheriot::Vmandnot; |
| using ::mpact::sim::cheriot::Vmnand; |
| using ::mpact::sim::cheriot::Vmnor; |
| using ::mpact::sim::cheriot::Vmor; |
| using ::mpact::sim::cheriot::Vmornot; |
| using ::mpact::sim::cheriot::Vmul; |
| using ::mpact::sim::cheriot::Vmulh; |
| using ::mpact::sim::cheriot::Vmulhsu; |
| using ::mpact::sim::cheriot::Vmulhu; |
| using ::mpact::sim::cheriot::Vmxnor; |
| using ::mpact::sim::cheriot::Vmxor; |
| using ::mpact::sim::cheriot::Vnmsac; |
| using ::mpact::sim::cheriot::Vnmsub; |
| using ::mpact::sim::cheriot::Vrem; |
| using ::mpact::sim::cheriot::Vremu; |
| using ::mpact::sim::cheriot::Vwadd; |
| using ::mpact::sim::cheriot::Vwaddu; |
| using ::mpact::sim::cheriot::Vwadduw; |
| using ::mpact::sim::cheriot::Vwaddw; |
| using ::mpact::sim::cheriot::Vwmacc; |
| using ::mpact::sim::cheriot::Vwmaccsu; |
| using ::mpact::sim::cheriot::Vwmaccu; |
| using ::mpact::sim::cheriot::Vwmaccus; |
| using ::mpact::sim::cheriot::Vwmul; |
| using ::mpact::sim::cheriot::Vwmulsu; |
| using ::mpact::sim::cheriot::Vwmulu; |
| using ::mpact::sim::cheriot::Vwsub; |
| using ::mpact::sim::cheriot::Vwsubu; |
| using ::mpact::sim::cheriot::Vwsubuw; |
| using ::mpact::sim::cheriot::Vwsubw; |
| |
| // Derived test class - adds a test helper function for testing the logical |
| // mask operation instructions. |
| class RiscVCheriotVectorOpmInstructionsTest |
| : public RiscVCheriotVectorInstructionsTestBase { |
| protected: |
| void BinaryLogicalMaskOpTestHelper(absl::string_view name, |
| std::function<bool(bool, bool)> op) { |
| uint8_t vs2_value[kVectorLengthInBytes]; |
| uint8_t vs1_value[kVectorLengthInBytes]; |
| uint8_t vd_value[kVectorLengthInBytes]; |
| FillArrayWithRandomValues<uint8_t>(vs2_value); |
| FillArrayWithRandomValues<uint8_t>(vs1_value); |
| FillArrayWithRandomValues<uint8_t>(vd_value); |
| AppendVectorRegisterOperands({kVs2, kVs1}, {kVd}); |
| for (int vstart : {0, 7, 32, 100, 250, 384}) { |
| for (int vlen_pct : {10, 20, 50, 100}) { |
| int vlen = |
| (kVectorLengthInBytes * 8 - vstart) * vlen_pct / 100 + vstart; |
| CHECK_LE(vlen, kVectorLengthInBytes * 8); |
| // Configure vector unit for different lmul settings. |
| uint32_t vtype = (kSewSettingsByByteSize[1] << 3) | kLmulSettings[6]; |
| ConfigureVectorUnit(vtype, vlen); |
| vlen = rv_vector_->vector_length(); |
| rv_vector_->set_vstart(vstart); |
| SetVectorRegisterValues<uint8_t>({{kVs2Name, vs2_value}, |
| {kVs1Name, vs1_value}, |
| {kVdName, vd_value}}); |
| instruction_->Execute(); |
| auto dst_span = vreg_[kVd]->data_buffer()->Get<uint8_t>(); |
| for (int i = 0; i < kVectorLengthInBytes * 8; i++) { |
| int mask_index = i >> 3; |
| int mask_offset = i & 0b111; |
| bool result = (dst_span[mask_index] >> mask_offset) & 0b1; |
| if ((i < vstart) || (i >= vlen)) { |
| bool vd = (vd_value[mask_index] >> mask_offset) & 0b1; |
| EXPECT_EQ(result, vd) << "[" << i << "] " << std::hex |
| << "vd: " << (int)vd_value[mask_index] |
| << " dst: " << (int)dst_span[mask_index]; |
| } else { |
| bool vs2 = (vs2_value[mask_index] >> mask_offset) & 0b1; |
| bool vs1 = (vs1_value[mask_index] >> mask_offset) & 0b1; |
| EXPECT_EQ(result, op(vs2, vs1)) |
| << "[" << i << "]: " << "op(" << vs2 << ", " << vs1 << ")"; |
| } |
| } |
| } |
| } |
| } |
| }; |
| |
| // Helper functions for averaging add and subtract. |
| template <typename T> |
| T VaaddHelper(RiscVCheriotVectorOpmInstructionsTest *tester, T vs2, T vs1) { |
| // Create two sums, lower nibble, and the upper part. Then combine after |
| // rounding. |
| T vs2_l = vs2 & 0xf; |
| T vs1_l = vs1 & 0xf; |
| T res_l = vs2_l + vs1_l; |
| T res = (vs2 >> 4) + (vs1 >> 4); |
| res_l += tester->RoundBits<T>(2, res_l) << 1; |
| // Add carry. |
| res += (res_l >> 4); |
| // Use unsigned type to avoid undefined behavior of left-shifting negative |
| // numbers. |
| using UT = typename std::make_unsigned<T>::type; |
| res = (absl::bit_cast<UT>(res) << 3) | ((res_l >> 1) & 0b111); |
| return res; |
| } |
| |
| template <typename T> |
| T VasubHelper(RiscVCheriotVectorOpmInstructionsTest *tester, T vs2, T vs1) { |
| // Create two diffs, lower nibble, and the upper part. Then combine after |
| // rounding. |
| T vs2_l = vs2 & 0xf; |
| T vs1_l = vs1 & 0xf; |
| T res_l = vs2_l - vs1_l; |
| T res_h = (vs2 >> 4) - (vs1 >> 4); |
| // Subtract borrow. |
| res_h -= ((res_l >> 4) & 0b1); |
| // Use unsigned type to avoid undefined behavior of left-shifting negative |
| // numbers. |
| using UT = typename std::make_unsigned<T>::type; |
| T res = (absl::bit_cast<UT>(res_h) << 3) | ((res_l >> 1) & 0b111); |
| res += tester->RoundBits<T>(2, res_l); |
| return res; |
| } |
| |
| // Vaaddu vector-vector test helper function. |
| template <typename T> |
| inline void VaadduVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| tester->SetSemanticFunction(&Vaaddu); |
| tester->BinaryOpTestHelperVV<T, T, T>( |
| absl::StrCat("Vaaddu", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [tester](T val0, T val1) -> T { |
| return VaaddHelper(tester, val0, val1); |
| }); |
| } |
| |
| // Vaaddu vector-scalar test helper function. |
| template <typename T> |
| inline void VaadduVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| tester->SetSemanticFunction(&Vaaddu); |
| tester->BinaryOpTestHelperVX<T, T, T>( |
| absl::StrCat("Vaaddu", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [tester](T val0, T val1) -> T { |
| return VaaddHelper(tester, val0, val1); |
| }); |
| } |
| |
| // Test Vaaddu instructions. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vaaddu) { |
| // vector-vector. |
| VaadduVVHelper<uint8_t>(this); |
| ResetInstruction(); |
| VaadduVVHelper<uint16_t>(this); |
| ResetInstruction(); |
| VaadduVVHelper<uint32_t>(this); |
| ResetInstruction(); |
| VaadduVVHelper<uint64_t>(this); |
| ResetInstruction(); |
| // vector-scalar. |
| VaadduVXHelper<uint8_t>(this); |
| ResetInstruction(); |
| VaadduVXHelper<uint16_t>(this); |
| ResetInstruction(); |
| VaadduVXHelper<uint32_t>(this); |
| ResetInstruction(); |
| VaadduVXHelper<uint64_t>(this); |
| } |
| |
| // Vaadd vector-vector test helper function. |
| template <typename T> |
| inline void VaaddVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| tester->SetSemanticFunction(&Vaadd); |
| tester->BinaryOpTestHelperVV<T, T, T>( |
| absl::StrCat("Vaaddu", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [tester](T val0, T val1) -> T { |
| return VaaddHelper(tester, val0, val1); |
| }); |
| } |
| |
| // Vaadd vector-vector test helper function. |
| template <typename T> |
| inline void VaaddVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| tester->SetSemanticFunction(&Vaadd); |
| tester->BinaryOpTestHelperVX<T, T, T>( |
| absl::StrCat("Vaaddu", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [tester](T val0, T val1) -> T { |
| return VaaddHelper(tester, val0, val1); |
| }); |
| } |
| |
| // Test Vaadd (signed) instructions. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vaadd) { |
| // Vector-vector. |
| VaaddVVHelper<int8_t>(this); |
| ResetInstruction(); |
| VaaddVVHelper<int16_t>(this); |
| ResetInstruction(); |
| VaaddVVHelper<int32_t>(this); |
| ResetInstruction(); |
| VaaddVVHelper<int64_t>(this); |
| // Vector-scalar. |
| ResetInstruction(); |
| VaaddVXHelper<int8_t>(this); |
| ResetInstruction(); |
| VaaddVXHelper<int16_t>(this); |
| ResetInstruction(); |
| VaaddVXHelper<int32_t>(this); |
| ResetInstruction(); |
| VaaddVXHelper<int64_t>(this); |
| } |
| |
| // Vasubu vector-vector test helper function. |
| template <typename T> |
| inline void VasubuVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| tester->SetSemanticFunction(&Vasubu); |
| tester->BinaryOpTestHelperVV<T, T, T>( |
| absl::StrCat("Vasubu", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [tester](T val0, T val1) -> T { |
| return VasubHelper(tester, val0, val1); |
| }); |
| } |
| // Vasubu vector-scalar test helper function. |
| template <typename T> |
| inline void VasubuVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| tester->SetSemanticFunction(&Vasubu); |
| tester->BinaryOpTestHelperVX<T, T, T>( |
| absl::StrCat("Vasubu", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [tester](T val0, T val1) -> T { |
| return VasubHelper(tester, val0, val1); |
| }); |
| } |
| |
| // Test Vasubu (unsigned) instructions. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vasubu) { |
| // Vector-vector. |
| VasubuVVHelper<uint8_t>(this); |
| ResetInstruction(); |
| VasubuVVHelper<uint16_t>(this); |
| ResetInstruction(); |
| VasubuVVHelper<uint32_t>(this); |
| ResetInstruction(); |
| VasubuVVHelper<uint64_t>(this); |
| ResetInstruction(); |
| // Vector-scalar. |
| VasubuVXHelper<uint8_t>(this); |
| ResetInstruction(); |
| VasubuVXHelper<uint16_t>(this); |
| ResetInstruction(); |
| VasubuVXHelper<uint32_t>(this); |
| ResetInstruction(); |
| VasubuVXHelper<uint64_t>(this); |
| } |
| |
| // Vasub vector-vector test helper function. |
| template <typename T> |
| inline void VasubVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| tester->SetSemanticFunction(&Vasub); |
| tester->BinaryOpTestHelperVV<T, T, T>( |
| absl::StrCat("Vasub", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [tester](T val0, T val1) -> T { |
| return VasubHelper(tester, val0, val1); |
| }); |
| } |
| // Vasub vector-scalar test helper function. |
| template <typename T> |
| inline void VasubVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| tester->SetSemanticFunction(&Vasub); |
| tester->BinaryOpTestHelperVX<T, T, T>( |
| absl::StrCat("Vasub", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [tester](T val0, T val1) -> T { |
| return VasubHelper(tester, val0, val1); |
| }); |
| } |
| |
| // Test Vasub (signed) instructions. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vasub) { |
| // Vector-vector. |
| VasubVVHelper<int8_t>(this); |
| ResetInstruction(); |
| VasubVVHelper<int16_t>(this); |
| ResetInstruction(); |
| VasubVVHelper<int32_t>(this); |
| ResetInstruction(); |
| VasubVVHelper<int64_t>(this); |
| ResetInstruction(); |
| // Vector-scalar. |
| VasubVXHelper<int8_t>(this); |
| ResetInstruction(); |
| VasubVXHelper<int16_t>(this); |
| ResetInstruction(); |
| VasubVXHelper<int32_t>(this); |
| ResetInstruction(); |
| VasubVXHelper<int64_t>(this); |
| } |
| |
| // Testing instructions that perform logical operations on vector masks. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vmandnot) { |
| SetSemanticFunction(&Vmandnot); |
| BinaryLogicalMaskOpTestHelper( |
| "Vmandnot", [](bool vs2, bool vs1) -> bool { return vs2 && !vs1; }); |
| } |
| |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vmand) { |
| SetSemanticFunction(&Vmand); |
| BinaryLogicalMaskOpTestHelper( |
| "Vmand", [](bool vs2, bool vs1) -> bool { return vs2 && vs1; }); |
| } |
| |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vmor) { |
| SetSemanticFunction(&Vmor); |
| BinaryLogicalMaskOpTestHelper( |
| "Vmor", [](bool vs2, bool vs1) -> bool { return vs2 || vs1; }); |
| } |
| |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vmxor) { |
| SetSemanticFunction(&Vmxor); |
| BinaryLogicalMaskOpTestHelper("Vmxor", [](bool vs2, bool vs1) -> bool { |
| return (vs1 && !vs2) || (!vs1 && vs2); |
| }); |
| } |
| |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vmornot) { |
| SetSemanticFunction(&Vmornot); |
| BinaryLogicalMaskOpTestHelper( |
| "Vmornot", [](bool vs2, bool vs1) -> bool { return vs2 || !vs1; }); |
| } |
| |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vmnand) { |
| SetSemanticFunction(&Vmnand); |
| BinaryLogicalMaskOpTestHelper( |
| "Vmnand", [](bool vs2, bool vs1) -> bool { return !(vs2 && vs1); }); |
| } |
| |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vmnor) { |
| SetSemanticFunction(&Vmnor); |
| BinaryLogicalMaskOpTestHelper( |
| "Vmnor", [](bool vs2, bool vs1) -> bool { return !(vs2 || vs1); }); |
| } |
| |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vmxnor) { |
| SetSemanticFunction(&Vmxnor); |
| BinaryLogicalMaskOpTestHelper("Vmxnor", [](bool vs2, bool vs1) -> bool { |
| return !((vs1 && !vs2) || (!vs1 && vs2)); |
| }); |
| } |
| |
| // Vdivu vector-vector test helper function. |
| template <typename T> |
| inline void VdivuVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| tester->SetSemanticFunction(&Vdivu); |
| tester->BinaryOpTestHelperVV<T, T, T>( |
| absl::StrCat("Vdivu", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1) -> T { |
| if (vs1 == 0) return ~vs1; |
| return vs2 / vs1; |
| }); |
| } |
| // Vdivu vector-scalar test helper function. |
| template <typename T> |
| inline void VdivuVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| tester->SetSemanticFunction(&Vdivu); |
| tester->BinaryOpTestHelperVX<T, T, T>( |
| absl::StrCat("Vdivu", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1) -> T { |
| if (vs1 == 0) return ~vs1; |
| return vs2 / vs1; |
| }); |
| } |
| |
| // Test vdivu instructions. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vdivu) { |
| // Vector-vector. |
| VdivuVVHelper<uint8_t>(this); |
| ResetInstruction(); |
| VdivuVVHelper<uint16_t>(this); |
| ResetInstruction(); |
| VdivuVVHelper<uint32_t>(this); |
| ResetInstruction(); |
| VdivuVVHelper<uint64_t>(this); |
| ResetInstruction(); |
| // Vector-scalar. |
| VdivuVXHelper<uint8_t>(this); |
| ResetInstruction(); |
| VdivuVXHelper<uint16_t>(this); |
| ResetInstruction(); |
| VdivuVXHelper<uint32_t>(this); |
| ResetInstruction(); |
| VdivuVXHelper<uint64_t>(this); |
| } |
| |
| // Vdiv vector-vector test helper function. |
| template <typename T> |
| inline void VdivVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| tester->SetSemanticFunction(&Vdiv); |
| tester->BinaryOpTestHelperVV<T, T, T>( |
| absl::StrCat("Vdiv", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1) -> T { |
| if (vs1 == 0) return ~vs1; |
| return vs2 / vs1; |
| }); |
| } |
| // Vdiv vector-scalar test helper function. |
| template <typename T> |
| inline void VdivVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| tester->SetSemanticFunction(&Vdiv); |
| tester->BinaryOpTestHelperVX<T, T, T>( |
| absl::StrCat("Vdiv", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1) -> T { |
| if (vs1 == 0) return ~vs1; |
| return vs2 / vs1; |
| }); |
| } |
| |
| // Test vector-vector vdiv instructions. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vdiv) { |
| // Vector-vector. |
| VdivVVHelper<int8_t>(this); |
| ResetInstruction(); |
| VdivVVHelper<int16_t>(this); |
| ResetInstruction(); |
| VdivVVHelper<int32_t>(this); |
| ResetInstruction(); |
| VdivVVHelper<int64_t>(this); |
| ResetInstruction(); |
| // Vector-scalar. |
| VdivVXHelper<int8_t>(this); |
| ResetInstruction(); |
| VdivVXHelper<int16_t>(this); |
| ResetInstruction(); |
| VdivVXHelper<int32_t>(this); |
| ResetInstruction(); |
| VdivVXHelper<int64_t>(this); |
| } |
| |
| // Vremu vector-vector test helper function. |
| template <typename T> |
| inline void VremuVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| tester->SetSemanticFunction(&Vremu); |
| tester->BinaryOpTestHelperVV<T, T, T>( |
| absl::StrCat("Vremu", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1) -> T { |
| if (vs1 == 0) return vs2; |
| return vs2 % vs1; |
| }); |
| } |
| // Vremu vector-scalar test helper function. |
| template <typename T> |
| inline void VremuVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| tester->SetSemanticFunction(&Vremu); |
| tester->BinaryOpTestHelperVX<T, T, T>( |
| absl::StrCat("Vremu", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1) -> T { |
| if (vs1 == 0) return vs2; |
| return vs2 % vs1; |
| }); |
| } |
| |
| // Test vremu instructions. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vremu) { |
| // Vector-vector. |
| VremuVVHelper<uint8_t>(this); |
| ResetInstruction(); |
| VremuVVHelper<uint16_t>(this); |
| ResetInstruction(); |
| VremuVVHelper<uint32_t>(this); |
| ResetInstruction(); |
| VremuVVHelper<uint64_t>(this); |
| ResetInstruction(); |
| // Vector-scalar. |
| VremuVXHelper<uint8_t>(this); |
| ResetInstruction(); |
| VremuVXHelper<uint16_t>(this); |
| ResetInstruction(); |
| VremuVXHelper<uint32_t>(this); |
| ResetInstruction(); |
| VremuVXHelper<uint64_t>(this); |
| } |
| |
| // Vrem vector-vector test helper function. |
| template <typename T> |
| inline void VremVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| tester->SetSemanticFunction(&Vrem); |
| tester->BinaryOpTestHelperVV<T, T, T>( |
| absl::StrCat("Vrem", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1) -> T { |
| if (vs1 == 0) return vs2; |
| return vs2 % vs1; |
| }); |
| } |
| // Vrem vector-scalar test helper function. |
| template <typename T> |
| inline void VremVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| tester->SetSemanticFunction(&Vrem); |
| tester->BinaryOpTestHelperVX<T, T, T>( |
| absl::StrCat("Vrem", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1) -> T { |
| if (vs1 == 0) return vs2; |
| return vs2 % vs1; |
| }); |
| } |
| |
| // Test vector-vector vrem instructions. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vrem) { |
| // vector-vector. |
| VremVVHelper<int8_t>(this); |
| ResetInstruction(); |
| VremVVHelper<int16_t>(this); |
| ResetInstruction(); |
| VremVVHelper<int32_t>(this); |
| ResetInstruction(); |
| VremVVHelper<int64_t>(this); |
| ResetInstruction(); |
| // vector-scalar. |
| VremVXHelper<int8_t>(this); |
| ResetInstruction(); |
| VremVXHelper<int16_t>(this); |
| ResetInstruction(); |
| VremVXHelper<int32_t>(this); |
| ResetInstruction(); |
| VremVXHelper<int64_t>(this); |
| } |
| |
| // Vmulhu vector-vector test helper function. |
| template <typename T> |
| inline void VmulhuVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| tester->SetSemanticFunction(&Vmulhu); |
| tester->BinaryOpTestHelperVV<T, T, T>( |
| absl::StrCat("Vmulhu", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1) -> T { |
| absl::uint128 vs2_w = static_cast<absl::uint128>(vs2); |
| absl::uint128 vs1_w = static_cast<absl::uint128>(vs1); |
| absl::uint128 vd_w = (vs2_w * vs1_w) >> (sizeof(T) * 8); |
| return static_cast<T>(vd_w); |
| }); |
| } |
| // Vmulhu vector-scalar test helper function. |
| template <typename T> |
| inline void VmulhuVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| tester->SetSemanticFunction(&Vmulhu); |
| tester->BinaryOpTestHelperVX<T, T, T>( |
| absl::StrCat("Vmulhu", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1) -> T { |
| absl::uint128 vs2_w = static_cast<absl::uint128>(vs2); |
| absl::uint128 vs1_w = static_cast<absl::uint128>(vs1); |
| absl::uint128 vd_w = (vs2_w * vs1_w) >> (sizeof(T) * 8); |
| return static_cast<T>(vd_w); |
| }); |
| } |
| |
| // Test vector-vector vmulhu instructions. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vmulhu) { |
| // vector-vector. |
| VmulhuVVHelper<uint8_t>(this); |
| ResetInstruction(); |
| VmulhuVVHelper<uint16_t>(this); |
| ResetInstruction(); |
| VmulhuVVHelper<uint32_t>(this); |
| ResetInstruction(); |
| VmulhuVVHelper<uint64_t>(this); |
| ResetInstruction(); |
| // vector-scalar. |
| VmulhuVXHelper<uint8_t>(this); |
| ResetInstruction(); |
| VmulhuVXHelper<uint16_t>(this); |
| ResetInstruction(); |
| VmulhuVXHelper<uint32_t>(this); |
| ResetInstruction(); |
| VmulhuVXHelper<uint64_t>(this); |
| } |
| |
| // Vmulh vector-vector test helper function. |
| template <typename T> |
| inline void VmulhVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| tester->SetSemanticFunction(&Vmulh); |
| tester->BinaryOpTestHelperVV<T, T, T>( |
| absl::StrCat("Vmulh", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1) -> T { |
| absl::int128 vs2_w = static_cast<absl::int128>(vs2); |
| absl::int128 vs1_w = static_cast<absl::int128>(vs1); |
| absl::int128 vd_w = (vs2_w * vs1_w) >> (sizeof(T) * 8); |
| return static_cast<T>(vd_w); |
| }); |
| } |
| |
| // Vmulh vector-scalar test helper function. |
| template <typename T> |
| inline void VmulhVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| tester->SetSemanticFunction(&Vmulh); |
| tester->BinaryOpTestHelperVX<T, T, T>( |
| absl::StrCat("Vmulh", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1) -> T { |
| absl::int128 vs2_w = static_cast<absl::int128>(vs2); |
| absl::int128 vs1_w = static_cast<absl::int128>(vs1); |
| absl::int128 vd_w = (vs2_w * vs1_w) >> (sizeof(T) * 8); |
| return static_cast<T>(vd_w); |
| }); |
| } |
| |
| // Test vector-vector vmulh instructions. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vmulh) { |
| // vector-vector. |
| VmulhVVHelper<int8_t>(this); |
| ResetInstruction(); |
| VmulhVVHelper<int16_t>(this); |
| ResetInstruction(); |
| VmulhVVHelper<int32_t>(this); |
| ResetInstruction(); |
| VmulhVVHelper<int64_t>(this); |
| ResetInstruction(); |
| // vector-scalar. |
| VmulhVXHelper<int8_t>(this); |
| ResetInstruction(); |
| VmulhVXHelper<int16_t>(this); |
| ResetInstruction(); |
| VmulhVXHelper<int32_t>(this); |
| ResetInstruction(); |
| VmulhVXHelper<int64_t>(this); |
| } |
| |
| // Vmul vector-vector test helper function. |
| template <typename T> |
| inline void VmulVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| tester->SetSemanticFunction(&Vmul); |
| tester->BinaryOpTestHelperVV<T, T, T>( |
| absl::StrCat("Vmul", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1) -> T { |
| return static_cast<T>(static_cast<WT>(vs2) * static_cast<WT>(vs1)); |
| }); |
| } |
| |
| // Vmul vector-scalar test helper function. |
| template <typename T> |
| inline void VmulVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| tester->SetSemanticFunction(&Vmul); |
| tester->BinaryOpTestHelperVX<T, T, T>( |
| absl::StrCat("Vmul", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1) -> T { |
| return static_cast<T>(static_cast<WT>(vs2) * static_cast<WT>(vs1)); |
| }); |
| } |
| |
| // Test vmulh instructions. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vmul) { |
| // vector-vector. |
| VmulVVHelper<int8_t>(this); |
| ResetInstruction(); |
| VmulVVHelper<int16_t>(this); |
| ResetInstruction(); |
| VmulVVHelper<int32_t>(this); |
| ResetInstruction(); |
| VmulVVHelper<int64_t>(this); |
| ResetInstruction(); |
| // vector-scalar. |
| VmulVXHelper<int8_t>(this); |
| ResetInstruction(); |
| VmulVXHelper<int16_t>(this); |
| ResetInstruction(); |
| VmulVXHelper<int32_t>(this); |
| ResetInstruction(); |
| VmulVXHelper<int64_t>(this); |
| } |
| |
| // Vmulhsu vector-vector test helper function. |
| template <typename T> |
| inline void VmulhsuVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using ST = typename std::make_signed<T>::type; |
| tester->SetSemanticFunction(&Vmulhsu); |
| tester->BinaryOpTestHelperVV<T, ST, T>( |
| absl::StrCat("Vmulhsu", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](ST vs2, T vs1) -> T { |
| absl::int128 vs2_w = static_cast<absl::int128>(vs2); |
| absl::int128 vs1_w = static_cast<absl::int128>(vs1); |
| absl::int128 res = (vs2_w * vs1_w) >> (sizeof(T) * 8); |
| return static_cast<ST>(res); |
| }); |
| } |
| |
| // Vmulhsu vector-scalar test helper function. |
| template <typename T> |
| inline void VmulhsuVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using ST = typename std::make_signed<T>::type; |
| tester->SetSemanticFunction(&Vmulhsu); |
| tester->BinaryOpTestHelperVX<T, ST, T>( |
| absl::StrCat("Vmulhsu", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](ST vs2, T vs1) -> T { |
| absl::int128 vs2_w = static_cast<absl::int128>(vs2); |
| absl::int128 vs1_w = static_cast<absl::int128>(vs1); |
| absl::int128 res = (vs2_w * vs1_w) >> (sizeof(T) * 8); |
| return static_cast<ST>(res); |
| }); |
| } |
| |
| // Test vmulhsu instructions. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vmulhsu) { |
| // vector-vector |
| VmulhsuVVHelper<uint8_t>(this); |
| ResetInstruction(); |
| VmulhsuVVHelper<uint16_t>(this); |
| ResetInstruction(); |
| VmulhsuVVHelper<uint32_t>(this); |
| ResetInstruction(); |
| VmulhsuVVHelper<uint64_t>(this); |
| ResetInstruction(); |
| // vector-scalar |
| VmulhsuVXHelper<uint8_t>(this); |
| ResetInstruction(); |
| VmulhsuVXHelper<uint16_t>(this); |
| ResetInstruction(); |
| VmulhsuVXHelper<uint32_t>(this); |
| ResetInstruction(); |
| VmulhsuVXHelper<uint64_t>(this); |
| } |
| |
| // Vmadd vector-vector test helper function. |
| template <typename T> |
| inline void VmaddVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| tester->SetSemanticFunction(&Vmadd); |
| tester->TernaryOpTestHelperVV<T, T, T>( |
| absl::StrCat("Vmadd", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1, T vd) { |
| if (sizeof(T) < 4) { |
| uint32_t vs1_32 = vs1; |
| uint32_t vs2_32 = vs2; |
| uint32_t vd_32 = vd; |
| return static_cast<T>((vs1_32 * vd_32) + vs2_32); |
| } |
| T res = vs1 * vd + vs2; |
| return res; |
| }); |
| } |
| |
| // Vmadd vector-scalar test helper function. |
| template <typename T> |
| inline void VmaddVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| tester->SetSemanticFunction(&Vmadd); |
| tester->TernaryOpTestHelperVX<T, T, T>( |
| absl::StrCat("Vmadd", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1, T vd) { |
| if (sizeof(T) < 4) { |
| uint32_t vs1_32 = vs1; |
| uint32_t vs2_32 = vs2; |
| uint32_t vd_32 = vd; |
| return static_cast<T>((vs1_32 * vd_32) + vs2_32); |
| } |
| T res = vs1 * vd + vs2; |
| return res; |
| }); |
| } |
| |
| // Test vmadd instructions. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vmadd) { |
| // vector-vector |
| VmaddVVHelper<uint8_t>(this); |
| ResetInstruction(); |
| VmaddVVHelper<uint16_t>(this); |
| ResetInstruction(); |
| VmaddVVHelper<uint32_t>(this); |
| ResetInstruction(); |
| VmaddVVHelper<uint64_t>(this); |
| ResetInstruction(); |
| // vector-scalar |
| VmaddVXHelper<uint8_t>(this); |
| ResetInstruction(); |
| VmaddVXHelper<uint16_t>(this); |
| ResetInstruction(); |
| VmaddVXHelper<uint32_t>(this); |
| ResetInstruction(); |
| VmaddVXHelper<uint64_t>(this); |
| } |
| |
| // Vnmsub vector-vector test helper function. |
| template <typename T> |
| inline void VnmsubVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| tester->SetSemanticFunction(&Vnmsub); |
| tester->TernaryOpTestHelperVV<T, T, T>( |
| absl::StrCat("Vnmsub", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1, T vd) { |
| if (sizeof(T) < 4) { |
| uint32_t vs1_32 = vs1; |
| uint32_t vs2_32 = vs2; |
| uint32_t vd_32 = vd; |
| return static_cast<T>(-(vs1_32 * vd_32) + vs2_32); |
| } |
| T res = -(vs1 * vd) + vs2; |
| return res; |
| }); |
| } |
| |
| // Vnmsub vector-scalar test helper function. |
| template <typename T> |
| inline void VnmsubVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| tester->SetSemanticFunction(&Vnmsub); |
| tester->TernaryOpTestHelperVX<T, T, T>( |
| absl::StrCat("Vnmsub", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1, T vd) { |
| if (sizeof(T) < 4) { |
| uint32_t vs1_32 = vs1; |
| uint32_t vs2_32 = vs2; |
| uint32_t vd_32 = vd; |
| return static_cast<T>(-(vs1_32 * vd_32) + vs2_32); |
| } |
| T res = -(vs1 * vd) + vs2; |
| return res; |
| }); |
| } |
| |
| // Test vnmsub instructions. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vnmsub) { |
| // vector-vector |
| VnmsubVVHelper<uint8_t>(this); |
| ResetInstruction(); |
| VnmsubVVHelper<uint16_t>(this); |
| ResetInstruction(); |
| VnmsubVVHelper<uint32_t>(this); |
| ResetInstruction(); |
| VnmsubVVHelper<uint64_t>(this); |
| ResetInstruction(); |
| // vector-scalar |
| VnmsubVXHelper<uint8_t>(this); |
| ResetInstruction(); |
| VnmsubVXHelper<uint16_t>(this); |
| ResetInstruction(); |
| VnmsubVXHelper<uint32_t>(this); |
| ResetInstruction(); |
| VnmsubVXHelper<uint64_t>(this); |
| } |
| |
| // Vmacc vector-vector test helper function. |
| template <typename T> |
| inline void VmaccVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| tester->SetSemanticFunction(&Vmacc); |
| tester->TernaryOpTestHelperVV<T, T, T>( |
| absl::StrCat("Vmacc", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1, T vd) { |
| if (sizeof(T) < 4) { |
| uint32_t vs1_32 = vs1; |
| uint32_t vs2_32 = vs2; |
| uint32_t vd_32 = vd; |
| return static_cast<T>((vs1_32 * vs2_32) + vd_32); |
| } |
| T res = (vs1 * vs2) + vd; |
| return res; |
| }); |
| } |
| |
| // Vmacc vector-scalar test helper function. |
| template <typename T> |
| inline void VmaccVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| tester->SetSemanticFunction(&Vmacc); |
| tester->TernaryOpTestHelperVX<T, T, T>( |
| absl::StrCat("Vmacc", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1, T vd) { |
| if (sizeof(T) < 4) { |
| uint32_t vs1_32 = vs1; |
| uint32_t vs2_32 = vs2; |
| uint32_t vd_32 = vd; |
| return static_cast<T>((vs1_32 * vs2_32) + vd_32); |
| } |
| T res = (vs1 * vs2) + vd; |
| return res; |
| }); |
| } |
| |
| // Test vmacc instructions. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vmacc) { |
| // vector-vector |
| VmaccVVHelper<uint8_t>(this); |
| ResetInstruction(); |
| VmaccVVHelper<uint16_t>(this); |
| ResetInstruction(); |
| VmaccVVHelper<uint32_t>(this); |
| ResetInstruction(); |
| VmaccVVHelper<uint64_t>(this); |
| ResetInstruction(); |
| // vector-scalar |
| VmaccVXHelper<uint8_t>(this); |
| ResetInstruction(); |
| VmaccVXHelper<uint16_t>(this); |
| ResetInstruction(); |
| VmaccVXHelper<uint32_t>(this); |
| ResetInstruction(); |
| VmaccVXHelper<uint64_t>(this); |
| } |
| |
| // Vnmsac vector-vector test helper function. |
| template <typename T> |
| inline void VnmsacVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| tester->SetSemanticFunction(&Vnmsac); |
| tester->TernaryOpTestHelperVV<T, T, T>( |
| absl::StrCat("Vnmsac", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1, T vd) { |
| if (sizeof(T) < 4) { |
| uint32_t vs1_32 = vs1; |
| uint32_t vs2_32 = vs2; |
| uint32_t vd_32 = vd; |
| return static_cast<T>(-(vs1_32 * vs2_32) + vd_32); |
| } |
| T res = -(vs1 * vs2) + vd; |
| return res; |
| }); |
| } |
| |
| // Vnmsac vector-scalar test helper function. |
| template <typename T> |
| inline void VnmsacVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| tester->SetSemanticFunction(&Vnmsac); |
| tester->TernaryOpTestHelperVX<T, T, T>( |
| absl::StrCat("Vnmsac", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1, T vd) { |
| if (sizeof(T) < 4) { |
| uint32_t vs1_32 = vs1; |
| uint32_t vs2_32 = vs2; |
| uint32_t vd_32 = vd; |
| return static_cast<T>(-(vs1_32 * vs2_32) + vd_32); |
| } |
| T res = -(vs1 * vs2) + vd; |
| return res; |
| }); |
| } |
| |
| // Test vnmsac instructions. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vnmsac) { |
| // vector-vector |
| VnmsacVVHelper<uint8_t>(this); |
| ResetInstruction(); |
| VnmsacVVHelper<uint16_t>(this); |
| ResetInstruction(); |
| VnmsacVVHelper<uint32_t>(this); |
| ResetInstruction(); |
| VnmsacVVHelper<uint64_t>(this); |
| ResetInstruction(); |
| // vector-scalar |
| VnmsacVXHelper<uint8_t>(this); |
| ResetInstruction(); |
| VnmsacVXHelper<uint16_t>(this); |
| ResetInstruction(); |
| VnmsacVXHelper<uint32_t>(this); |
| ResetInstruction(); |
| VnmsacVXHelper<uint64_t>(this); |
| } |
| |
| // Vwaddu vector-vector test helper function. |
| template <typename T> |
| inline void VwadduVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| tester->SetSemanticFunction(&Vwaddu); |
| tester->BinaryOpTestHelperVV<WT, T, T>( |
| absl::StrCat("Vwaddu", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1) -> WT { |
| return static_cast<WT>(vs2) + static_cast<WT>(vs1); |
| }); |
| } |
| |
| // Vwaddu vector-scalar test helper function. |
| template <typename T> |
| inline void VwadduVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| tester->SetSemanticFunction(&Vwaddu); |
| tester->BinaryOpTestHelperVX<WT, T, T>( |
| absl::StrCat("Vwaddu", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1) -> WT { |
| return static_cast<WT>(vs2) + static_cast<WT>(vs1); |
| }); |
| } |
| |
| // Vector widening unsigned add. (sew * 2) = sew + sew |
| // There is no test for sew == 64 bits, as this is a widening operation, |
| // and 64 bit values are the max sized vector elements. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vwaddu) { |
| // vector-vector. |
| VwadduVVHelper<uint8_t>(this); |
| ResetInstruction(); |
| VwadduVVHelper<uint16_t>(this); |
| ResetInstruction(); |
| VwadduVVHelper<uint32_t>(this); |
| ResetInstruction(); |
| // vector-scalar. |
| VwadduVXHelper<uint8_t>(this); |
| ResetInstruction(); |
| VwadduVXHelper<uint16_t>(this); |
| ResetInstruction(); |
| VwadduVXHelper<uint32_t>(this); |
| } |
| |
| // Vwsubu vector-vector test helper function. |
| template <typename T> |
| inline void VwsubuVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| tester->SetSemanticFunction(&Vwsubu); |
| tester->BinaryOpTestHelperVV<WT, T, T>( |
| absl::StrCat("Vwsubu", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1) -> WT { |
| return static_cast<WT>(vs2) - static_cast<WT>(vs1); |
| }); |
| } |
| |
| // Vwsubu vector-scalar test helper function. |
| template <typename T> |
| inline void VwsubuVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| tester->SetSemanticFunction(&Vwsubu); |
| tester->BinaryOpTestHelperVX<WT, T, T>( |
| absl::StrCat("Vwsubu", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1) -> WT { |
| return static_cast<WT>(vs2) - static_cast<WT>(vs1); |
| }); |
| } |
| |
| // Vector widening unsigned subtract. (sew * 2) = sew + sew |
| // There is no test for sew == 64 bits, as this is a widening operation, |
| // and 64 bit values are the max sized vector elements. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vwsubu) { |
| // vector-vector. |
| VwsubuVVHelper<uint8_t>(this); |
| ResetInstruction(); |
| VwsubuVVHelper<uint16_t>(this); |
| ResetInstruction(); |
| VwsubuVVHelper<uint32_t>(this); |
| ResetInstruction(); |
| // vector-scalar. |
| VwsubuVXHelper<uint8_t>(this); |
| ResetInstruction(); |
| VwsubuVXHelper<uint16_t>(this); |
| ResetInstruction(); |
| VwsubuVXHelper<uint32_t>(this); |
| } |
| |
| // Vwadd vector-vector test helper function. |
| template <typename T> |
| inline void VwaddVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| tester->SetSemanticFunction(&Vwadd); |
| tester->BinaryOpTestHelperVV<WT, T, T>( |
| absl::StrCat("Vwadd", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1) -> WT { |
| return static_cast<WT>(vs2) + static_cast<WT>(vs1); |
| }); |
| } |
| |
| // Vwadd vector-scalar test helper function. |
| template <typename T> |
| inline void VwaddVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| tester->SetSemanticFunction(&Vwadd); |
| tester->BinaryOpTestHelperVX<WT, T, T>( |
| absl::StrCat("Vwadd", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1) -> WT { |
| return static_cast<WT>(vs2) + static_cast<WT>(vs1); |
| }); |
| } |
| |
| // Vector videning signed addition. (sew * 2) = sew + sew. |
| // There is no test for sew == 64 bits, as this is a widening operation, |
| // and 64 bit values are the max sized vector elements. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vwadd) { |
| // vector-vector. |
| VwaddVVHelper<int8_t>(this); |
| ResetInstruction(); |
| VwaddVVHelper<int16_t>(this); |
| ResetInstruction(); |
| VwaddVVHelper<int32_t>(this); |
| ResetInstruction(); |
| // vector-scalar. |
| VwaddVXHelper<int8_t>(this); |
| ResetInstruction(); |
| VwaddVXHelper<int16_t>(this); |
| ResetInstruction(); |
| VwaddVXHelper<int32_t>(this); |
| } |
| |
| // Vwsub vector-vector test helper function. |
| template <typename T> |
| inline void VwsubVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| tester->SetSemanticFunction(&Vwsub); |
| tester->BinaryOpTestHelperVV<WT, T, T>( |
| absl::StrCat("Vwsub", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1) -> WT { |
| WT vs2_w = vs2; |
| WT vs1_w = vs1; |
| WT res = vs2_w - vs1_w; |
| return res; |
| }); |
| } |
| |
| // Vwsub vector-scalar test helper function. |
| template <typename T> |
| inline void VwsubVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| tester->SetSemanticFunction(&Vwsub); |
| tester->BinaryOpTestHelperVX<WT, T, T>( |
| absl::StrCat("Vwsub", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1) -> WT { |
| WT vs2_w = vs2; |
| WT vs1_w = vs1; |
| WT res = vs2_w - vs1_w; |
| return res; |
| }); |
| } |
| |
| // Vector widening unsigned subtract. (sew * 2) = sew + sew |
| // There is no test for sew == 64 bits, as this is a widening operation, |
| // and 64 bit values are the max sized vector elements. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vwsub) { |
| // vector-vector. |
| VwsubVVHelper<int8_t>(this); |
| ResetInstruction(); |
| VwsubVVHelper<int16_t>(this); |
| ResetInstruction(); |
| VwsubVVHelper<int32_t>(this); |
| ResetInstruction(); |
| // vector-scalar. |
| VwsubVXHelper<int8_t>(this); |
| ResetInstruction(); |
| VwsubVXHelper<int16_t>(this); |
| ResetInstruction(); |
| VwsubVXHelper<int32_t>(this); |
| } |
| |
| // Vwadduw vector-vector test helper function. |
| template <typename T> |
| inline void VwadduwVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| tester->SetSemanticFunction(&Vwadduw); |
| tester->BinaryOpTestHelperVV<WT, WT, T>( |
| absl::StrCat("Vwadduw", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), |
| [](WT vs2, T vs1) -> WT { return vs2 + static_cast<WT>(vs1); }); |
| } |
| |
| // Vwadduw vector-scalar test helper function. |
| template <typename T> |
| inline void VwadduwVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| tester->SetSemanticFunction(&Vwadduw); |
| tester->BinaryOpTestHelperVX<WT, WT, T>( |
| absl::StrCat("Vwadduw", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), |
| [](WT vs2, T vs1) -> WT { return vs2 + static_cast<WT>(vs1); }); |
| } |
| |
| // Vector widening unsigned add. (sew * 2) = (sew * 2) + sew |
| // There is no test for sew == 64 bits, as this is a widening operation, |
| // and 64 bit values are the max sized vector elements. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vwadduw) { |
| // vector-vector. |
| VwadduwVVHelper<uint8_t>(this); |
| ResetInstruction(); |
| VwadduwVVHelper<uint16_t>(this); |
| ResetInstruction(); |
| VwadduwVVHelper<uint32_t>(this); |
| ResetInstruction(); |
| // vector-scalar. |
| VwadduwVXHelper<uint8_t>(this); |
| ResetInstruction(); |
| VwadduwVXHelper<uint16_t>(this); |
| ResetInstruction(); |
| VwadduwVXHelper<uint32_t>(this); |
| } |
| |
| // Vwsubuw vector-vector test helper function. |
| template <typename T> |
| inline void VwsubuwVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| tester->SetSemanticFunction(&Vwsubuw); |
| tester->BinaryOpTestHelperVV<WT, WT, T>( |
| absl::StrCat("Vwsubuw", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), |
| [](WT vs2, T vs1) -> WT { return vs2 - static_cast<WT>(vs1); }); |
| } |
| |
| // Vwsubuw vector-scalar test helper function. |
| template <typename T> |
| inline void VwsubuwVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| tester->SetSemanticFunction(&Vwsubuw); |
| tester->BinaryOpTestHelperVX<WT, WT, T>( |
| absl::StrCat("Vwsubuw", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), |
| [](WT vs2, T vs1) -> WT { return vs2 - static_cast<WT>(vs1); }); |
| } |
| |
| // Vector widening unsigned subtract. (sew * 2) = (sew * 2) + sew |
| // There is no test for sew == 64 bits, as this is a widening operation, |
| // and 64 bit values are the max sized vector elements. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vwsubuw) { |
| // vector-vector. |
| VwsubuwVVHelper<uint8_t>(this); |
| ResetInstruction(); |
| VwsubuwVVHelper<uint16_t>(this); |
| ResetInstruction(); |
| VwsubuwVVHelper<uint32_t>(this); |
| ResetInstruction(); |
| // vector-scalar. |
| VwsubuwVXHelper<uint8_t>(this); |
| ResetInstruction(); |
| VwsubuwVXHelper<uint16_t>(this); |
| ResetInstruction(); |
| VwsubuwVXHelper<uint32_t>(this); |
| } |
| |
| // Vwaddw vector-vector test helper function. |
| template <typename T> |
| inline void VwaddwVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| tester->SetSemanticFunction(&Vwaddw); |
| tester->BinaryOpTestHelperVV<WT, WT, T>( |
| absl::StrCat("Vwaddw", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), |
| [](WT vs2, T vs1) -> WT { return vs2 + static_cast<WT>(vs1); }); |
| } |
| |
| // Vwaddw vector-scalar test helper function. |
| template <typename T> |
| inline void VwaddwVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| tester->SetSemanticFunction(&Vwaddw); |
| tester->BinaryOpTestHelperVX<WT, WT, T>( |
| absl::StrCat("Vwaddw", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), |
| [](WT vs2, T vs1) -> WT { return vs2 + static_cast<WT>(vs1); }); |
| } |
| |
| // Vector widening signed add. (sew * 2) = (sew * 2) + sew |
| // There is no test for sew == 64 bits, as this is a widening operation, |
| // and 64 bit values are the max sized vector elements. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vwaddw) { |
| // vector-vector. |
| VwaddwVVHelper<int8_t>(this); |
| ResetInstruction(); |
| VwaddwVVHelper<int16_t>(this); |
| ResetInstruction(); |
| VwaddwVVHelper<int32_t>(this); |
| ResetInstruction(); |
| // vector-scalar. |
| VwaddwVXHelper<int8_t>(this); |
| ResetInstruction(); |
| VwaddwVXHelper<int16_t>(this); |
| ResetInstruction(); |
| VwaddwVXHelper<int32_t>(this); |
| } |
| |
| // Vwsubw vector-vector test helper function. |
| template <typename T> |
| inline void VwsubwVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| tester->SetSemanticFunction(&Vwsubw); |
| tester->BinaryOpTestHelperVV<WT, WT, T>( |
| absl::StrCat("Vwsubw", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), |
| [](WT vs2, T vs1) -> WT { return vs2 - static_cast<WT>(vs1); }); |
| } |
| |
| // Vwsubw vector-scalar test helper function. |
| template <typename T> |
| inline void VwsubwVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| tester->SetSemanticFunction(&Vwsubw); |
| tester->BinaryOpTestHelperVX<WT, WT, T>( |
| absl::StrCat("Vwsubw", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), |
| [](WT vs2, T vs1) -> WT { return vs2 - static_cast<WT>(vs1); }); |
| } |
| |
| // Vector widening signed subtract. (sew * 2) = (sew * 2) + sew |
| // There is no test for sew == 64 bits, as this is a widening operation, |
| // and 64 bit values are the max sized vector elements. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vwsubw) { |
| // vector-vector. |
| VwsubwVVHelper<int8_t>(this); |
| ResetInstruction(); |
| VwsubwVVHelper<int16_t>(this); |
| ResetInstruction(); |
| VwsubwVVHelper<int32_t>(this); |
| ResetInstruction(); |
| // vector-scalar. |
| VwsubwVXHelper<int8_t>(this); |
| ResetInstruction(); |
| VwsubwVXHelper<int16_t>(this); |
| ResetInstruction(); |
| VwsubwVXHelper<int32_t>(this); |
| } |
| |
| // Vwmul vector-vector test helper function. |
| template <typename T> |
| inline void VwmuluVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| tester->SetSemanticFunction(&Vwmulu); |
| tester->BinaryOpTestHelperVV<WT, T, T>( |
| absl::StrCat("Vwmulu", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1) -> WT { |
| return static_cast<WT>(vs2) * static_cast<WT>(vs1); |
| }); |
| } |
| |
| // Vwmulu vector-scalar test helper function. |
| template <typename T> |
| inline void VwmuluVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| tester->SetSemanticFunction(&Vwmulu); |
| tester->BinaryOpTestHelperVX<WT, T, T>( |
| absl::StrCat("Vwmulu", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1) -> WT { |
| return static_cast<WT>(vs2) * static_cast<WT>(vs1); |
| }); |
| } |
| |
| // Vector widening signed multiply. (sew * 2) = sew + sew |
| // There is no test for sew == 64 bits, as this is a widening operation, |
| // and 64 bit values are the max sized vector elements. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vwmulu) { |
| // vector-vector. |
| VwmuluVVHelper<uint8_t>(this); |
| ResetInstruction(); |
| VwmuluVVHelper<uint16_t>(this); |
| ResetInstruction(); |
| VwmuluVVHelper<uint32_t>(this); |
| ResetInstruction(); |
| // vector-scalar. |
| VwmuluVXHelper<uint8_t>(this); |
| ResetInstruction(); |
| VwmuluVXHelper<uint16_t>(this); |
| ResetInstruction(); |
| VwmuluVXHelper<uint32_t>(this); |
| } |
| |
| // Vwmul vector-vector test helper function. |
| template <typename T> |
| inline void VwmulVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| tester->SetSemanticFunction(&Vwmul); |
| tester->BinaryOpTestHelperVV<WT, T, T>( |
| absl::StrCat("Vwmul", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1) -> WT { |
| return static_cast<WT>(vs2) * static_cast<WT>(vs1); |
| }); |
| } |
| |
| // Vwmul vector-scalar test helper function. |
| template <typename T> |
| inline void VwmulVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| tester->SetSemanticFunction(&Vwmul); |
| tester->BinaryOpTestHelperVX<WT, T, T>( |
| absl::StrCat("Vwmul", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1) -> WT { |
| return static_cast<WT>(vs2) * static_cast<WT>(vs1); |
| }); |
| } |
| |
| // Vector widening signed multiply. (sew * 2) = sew + sew |
| // There is no test for sew == 64 bits, as this is a widening operation, |
| // and 64 bit values are the max sized vector elements. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vwmul) { |
| // vector-vector. |
| VwmulVVHelper<int8_t>(this); |
| ResetInstruction(); |
| VwmulVVHelper<int16_t>(this); |
| ResetInstruction(); |
| VwmulVVHelper<int32_t>(this); |
| ResetInstruction(); |
| // vector-scalar. |
| VwmulVXHelper<int8_t>(this); |
| ResetInstruction(); |
| VwmulVXHelper<int16_t>(this); |
| ResetInstruction(); |
| VwmulVXHelper<int32_t>(this); |
| } |
| |
| // Vwmul vector-vector test helper function. |
| template <typename T> |
| inline void VwmulsuVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| using UT = typename std::make_unsigned<T>::type; |
| tester->SetSemanticFunction(&Vwmulsu); |
| tester->BinaryOpTestHelperVV<WT, T, T>( |
| absl::StrCat("Vwmulsu", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, UT vs1) -> WT { |
| return static_cast<WT>(vs2) * static_cast<WT>(vs1); |
| }); |
| } |
| |
| // Vwmulsu vector-scalar test helper function. |
| template <typename T> |
| inline void VwmulsuVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| using UT = typename std::make_unsigned<T>::type; |
| tester->SetSemanticFunction(&Vwmulsu); |
| tester->BinaryOpTestHelperVX<WT, T, T>( |
| absl::StrCat("Vwmulsu", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, UT vs1) -> WT { |
| return static_cast<WT>(vs2) * static_cast<WT>(vs1); |
| }); |
| } |
| |
| // Vector widening signed multiply. (sew * 2) = sew + sew |
| // There is no test for sew == 64 bits, as this is a widening operation, |
| // and 64 bit values are the max sized vector elements. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vwmulsu) { |
| // vector-vector. |
| VwmulsuVVHelper<int8_t>(this); |
| ResetInstruction(); |
| VwmulsuVVHelper<int16_t>(this); |
| ResetInstruction(); |
| VwmulsuVVHelper<int32_t>(this); |
| ResetInstruction(); |
| // vector-scalar. |
| VwmulsuVXHelper<int8_t>(this); |
| ResetInstruction(); |
| VwmulsuVXHelper<int16_t>(this); |
| ResetInstruction(); |
| VwmulsuVXHelper<int32_t>(this); |
| } |
| |
| // Vmaccu vector-vector test helper function. |
| template <typename T> |
| inline void VwmaccuVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| tester->SetSemanticFunction(&Vwmaccu); |
| tester->TernaryOpTestHelperVV<WT, T, T>( |
| absl::StrCat("Vwmaccu", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1, WT vd) { |
| return static_cast<WT>(vs2) * static_cast<WT>(vs1) + vd; |
| }); |
| } |
| |
| // Vwmaccu vector-scalar test helper function. |
| template <typename T> |
| inline void VwmaccuVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| tester->SetSemanticFunction(&Vwmaccu); |
| tester->TernaryOpTestHelperVX<WT, T, T>( |
| absl::StrCat("Vwmaccu", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1, WT vd) { |
| return static_cast<WT>(vs2) * static_cast<WT>(vs1) + vd; |
| }); |
| } |
| |
| // Test vwmaccu instructions. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vwmaccu) { |
| // vector-vector |
| VwmaccuVVHelper<uint8_t>(this); |
| ResetInstruction(); |
| VwmaccuVVHelper<uint16_t>(this); |
| ResetInstruction(); |
| VwmaccuVVHelper<uint32_t>(this); |
| ResetInstruction(); |
| // vector-scalar |
| VwmaccuVXHelper<uint8_t>(this); |
| ResetInstruction(); |
| VwmaccuVXHelper<uint16_t>(this); |
| ResetInstruction(); |
| VwmaccuVXHelper<uint32_t>(this); |
| } |
| |
| // Vmacc vector-vector test helper function. |
| template <typename T> |
| inline void VwmaccVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| tester->SetSemanticFunction(&Vwmacc); |
| tester->TernaryOpTestHelperVV<WT, T, T>( |
| absl::StrCat("Vwmacc", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1, WT vd) -> WT { |
| WT vs1_w = vs1; |
| WT vs2_w = vs2; |
| WT prod = vs1_w * vs2_w; |
| using UWT = typename std::make_unsigned<WT>::type; |
| WT res = absl::bit_cast<UWT>(prod) + absl::bit_cast<UWT>(vd); |
| return res; |
| }); |
| } |
| |
| // Vwmacc vector-scalar test helper function. |
| template <typename T> |
| inline void VwmaccVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| tester->SetSemanticFunction(&Vwmacc); |
| tester->TernaryOpTestHelperVX<WT, T, T>( |
| absl::StrCat("Vwmacc", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, T vs1, WT vd) -> WT { |
| WT vs1_w = vs1; |
| WT vs2_w = vs2; |
| WT prod = vs1_w * vs2_w; |
| using UWT = typename std::make_unsigned<WT>::type; |
| WT res = absl::bit_cast<UWT>(prod) + absl::bit_cast<UWT>(vd); |
| return res; |
| }); |
| } |
| |
| // Test vwmacc instructions. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vwmacc) { |
| // vector-vector |
| VwmaccVVHelper<int8_t>(this); |
| ResetInstruction(); |
| VwmaccVVHelper<int16_t>(this); |
| ResetInstruction(); |
| VwmaccVVHelper<int32_t>(this); |
| ResetInstruction(); |
| // vector-scalar |
| VwmaccVXHelper<int8_t>(this); |
| ResetInstruction(); |
| VwmaccVXHelper<int16_t>(this); |
| ResetInstruction(); |
| VwmaccVXHelper<int32_t>(this); |
| } |
| |
| // Vmaccus vector-vector test helper function. |
| template <typename T> |
| inline void VwmaccusVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| using UT = typename std::make_unsigned<T>::type; |
| tester->SetSemanticFunction(&Vwmaccus); |
| tester->TernaryOpTestHelperVV<WT, T, UT>( |
| absl::StrCat("Vwmaccus", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, UT vs1, WT vd) -> WT { |
| using UWT = typename std::make_unsigned<WT>::type; |
| UWT vs1_w = vs1; |
| WT vs2_w = vs2; |
| WT prod = vs1_w * vs2_w; |
| WT res = absl::bit_cast<UWT>(prod) + absl::bit_cast<UWT>(vd); |
| return res; |
| }); |
| } |
| |
| // Vwmaccus vector-scalar test helper function. |
| template <typename T> |
| inline void VwmaccusVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| using UT = typename std::make_unsigned<T>::type; |
| tester->SetSemanticFunction(&Vwmaccus); |
| tester->TernaryOpTestHelperVX<WT, T, UT>( |
| absl::StrCat("Vwmaccus", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](T vs2, UT vs1, WT vd) -> WT { |
| using UWT = typename std::make_unsigned<WT>::type; |
| UWT vs1_w = vs1; |
| WT vs2_w = vs2; |
| WT prod = vs1_w * vs2_w; |
| WT res = absl::bit_cast<UWT>(prod) + absl::bit_cast<UWT>(vd); |
| return res; |
| }); |
| } |
| |
| // Test vwmaccus instructions. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vwmaccus) { |
| // vector-vector |
| VwmaccusVVHelper<int8_t>(this); |
| ResetInstruction(); |
| VwmaccusVVHelper<int16_t>(this); |
| ResetInstruction(); |
| VwmaccusVVHelper<int32_t>(this); |
| ResetInstruction(); |
| // vector-scalar |
| VwmaccusVXHelper<int8_t>(this); |
| ResetInstruction(); |
| VwmaccusVXHelper<int16_t>(this); |
| ResetInstruction(); |
| VwmaccusVXHelper<int32_t>(this); |
| } |
| |
| // Vmaccsu vector-vector test helper function. |
| template <typename T> |
| inline void VwmaccsuVVHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| using UT = typename std::make_unsigned<T>::type; |
| tester->SetSemanticFunction(&Vwmaccsu); |
| tester->TernaryOpTestHelperVV<WT, UT, T>( |
| absl::StrCat("Vwmaccsu", sizeof(T) * 8, "vv"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](UT vs2, T vs1, WT vd) -> WT { |
| using UWT = typename std::make_unsigned<WT>::type; |
| WT vs1_w = vs1; |
| UWT vs2_w = vs2; |
| WT prod = vs1_w * vs2_w; |
| WT res = absl::bit_cast<UWT>(prod) + absl::bit_cast<UWT>(vd); |
| return res; |
| }); |
| } |
| |
| // Vwmaccsu vector-scalar test helper function. |
| template <typename T> |
| inline void VwmaccsuVXHelper(RiscVCheriotVectorOpmInstructionsTest *tester) { |
| using WT = typename WideType<T>::type; |
| using UT = typename std::make_unsigned<T>::type; |
| tester->SetSemanticFunction(&Vwmaccsu); |
| tester->TernaryOpTestHelperVX<WT, UT, T>( |
| absl::StrCat("Vwmaccsu", sizeof(T) * 8, "vx"), /*sew*/ sizeof(T) * 8, |
| tester->instruction(), [](UT vs2, T vs1, WT vd) -> WT { |
| using UWT = typename std::make_unsigned<WT>::type; |
| WT vs1_w = vs1; |
| UWT vs2_w = vs2; |
| WT prod = vs1_w * vs2_w; |
| WT res = absl::bit_cast<UWT>(prod) + absl::bit_cast<UWT>(vd); |
| return res; |
| }); |
| } |
| |
| // Test vwmaccsu instructions. |
| TEST_F(RiscVCheriotVectorOpmInstructionsTest, Vwmaccsu) { |
| // vector-vector |
| VwmaccsuVVHelper<int8_t>(this); |
| ResetInstruction(); |
| VwmaccsuVVHelper<int16_t>(this); |
| ResetInstruction(); |
| VwmaccsuVVHelper<int32_t>(this); |
| ResetInstruction(); |
| // vector-scalar |
| VwmaccsuVXHelper<int8_t>(this); |
| ResetInstruction(); |
| VwmaccsuVXHelper<int16_t>(this); |
| ResetInstruction(); |
| VwmaccsuVXHelper<int32_t>(this); |
| } |
| |
| } // namespace |