Add vst unit test
Change-Id: Ic01f1748bb2a7656d807a2c510c688d36ec2b013
diff --git a/tests/kelvin_isa/BUILD b/tests/kelvin_isa/BUILD
index 9986566..52865ac 100644
--- a/tests/kelvin_isa/BUILD
+++ b/tests/kelvin_isa/BUILD
@@ -221,6 +221,16 @@
)
kelvin_test(
+ name = "vst",
+ srcs = [
+ "vst.cc",
+ ],
+ deps = [
+ ":kelvin_test",
+ ],
+)
+
+kelvin_test(
name = "vstq",
srcs = [
"vstq.cc",
diff --git a/tests/kelvin_isa/vst.cc b/tests/kelvin_isa/vst.cc
new file mode 100644
index 0000000..11a5792
--- /dev/null
+++ b/tests/kelvin_isa/vst.cc
@@ -0,0 +1,729 @@
+/*
+ * 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
+ *
+ * http://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 "crt/printf_traits.h"
+#include "tests/kelvin_isa/kelvin_test.h"
+
+inline uint8_t* vstp_data(uint8_t* data) {
+ vst_b_p_x(v0, data);
+ return data;
+}
+
+inline uint16_t* vstp_data(uint16_t* data) {
+ vst_h_p_x(v0, data);
+ return data;
+}
+
+inline uint32_t* vstp_data(uint32_t* data) {
+ vst_w_p_x(v0, data);
+ return data;
+}
+
+inline uint8_t* vstpm_data(uint8_t* data) {
+ vst_b_p_x_m(v0, data);
+ return data;
+}
+
+inline uint16_t* vstpm_data(uint16_t* data) {
+ vst_h_p_x_m(v0, data);
+ return data;
+}
+
+inline uint32_t* vstpm_data(uint32_t* data) {
+ vst_w_p_x_m(v0, data);
+ return data;
+}
+
+inline uint8_t* vstlp_xx(uint8_t* data, int length) {
+ vst_b_lp_xx(v0, data, length);
+ return data;
+}
+
+inline uint16_t* vstlp_xx(uint16_t* data, int length) {
+ vst_h_lp_xx(v0, data, length);
+ return data;
+}
+
+inline uint32_t* vstlp_xx(uint32_t* data, int length) {
+ vst_w_lp_xx(v0, data, length);
+ return data;
+}
+
+inline uint8_t* vstlpm_xx(uint8_t* data, int length) {
+ vst_b_lp_xx_m(v0, data, length);
+ return data;
+}
+
+inline uint16_t* vstlpm_xx(uint16_t* data, int length) {
+ vst_h_lp_xx_m(v0, data, length);
+ return data;
+}
+
+inline uint32_t* vstlpm_xx(uint32_t* data, int length) {
+ vst_w_lp_xx_m(v0, data, length);
+ return data;
+}
+
+uint8_t* vstp_xx(uint8_t* data, int length) {
+ vst_b_p_xx(v0, data, length);
+ return data;
+}
+
+uint16_t* vstp_xx(uint16_t* data, int length) {
+ vst_h_p_xx(v0, data, length);
+ return data;
+}
+
+uint32_t* vstp_xx(uint32_t* data, int length) {
+ vst_w_p_xx(v0, data, length);
+ return data;
+}
+
+uint8_t* vstpm_xx(uint8_t* data, int length) {
+ vst_b_p_xx_m(v0, data, length);
+ return data;
+}
+
+uint16_t* vstpm_xx(uint16_t* data, int length) {
+ vst_h_p_xx_m(v0, data, length);
+ return data;
+}
+
+uint32_t* vstpm_xx(uint32_t* data, int length) {
+ vst_w_p_xx_m(v0, data, length);
+ return data;
+}
+
+uint8_t* vstsp_xx(uint8_t* data, int stride) {
+ vst_b_sp_xx(v0, data, stride);
+ return data;
+}
+
+uint16_t* vstsp_xx(uint16_t* data, int stride) {
+ vst_h_sp_xx(v0, data, stride);
+ return data;
+}
+
+uint32_t* vstsp_xx(uint32_t* data, int stride) {
+ vst_w_sp_xx(v0, data, stride);
+ return data;
+}
+
+uint8_t* vstspm_xx(uint8_t* data, int stride) {
+ vst_b_sp_xx_m(v0, data, stride);
+ return data;
+}
+
+uint16_t* vstspm_xx(uint16_t* data, int stride) {
+ vst_h_sp_xx_m(v0, data, stride);
+ return data;
+}
+
+uint32_t* vstspm_xx(uint32_t* data, int stride) {
+ vst_w_sp_xx_m(v0, data, stride);
+ return data;
+}
+
+uint8_t* vsttp_xx(uint8_t* data, int stride) {
+ vst_b_tp_xx(v0, data, stride);
+ return data;
+}
+
+uint16_t* vsttp_xx(uint16_t* data, int stride) {
+ vst_h_tp_xx(v0, data, stride);
+ return data;
+}
+
+uint32_t* vsttp_xx(uint32_t* data, int stride) {
+ vst_w_tp_xx(v0, data, stride);
+ return data;
+}
+
+uint8_t* vsttpm_xx(uint8_t* data, int stride) {
+ vst_b_tp_xx_m(v0, data, stride);
+ return data;
+}
+
+uint16_t* vsttpm_xx(uint16_t* data, int stride) {
+ vst_h_tp_xx_m(v0, data, stride);
+ return data;
+}
+
+uint32_t* vsttpm_xx(uint32_t* data, int stride) {
+ vst_w_tp_xx_m(v0, data, stride);
+ return data;
+}
+
+template <typename T>
+struct TypeString {
+ static const char* type_str() { return "<unknown>"; }
+};
+
+template <>
+struct TypeString<uint8_t> {
+ static const char* type_str() { return "<uint8_t>"; }
+};
+
+template <>
+struct TypeString<uint16_t> {
+ static const char* type_str() { return "<uint16_t>"; }
+};
+
+template <>
+struct TypeString<uint32_t> {
+ static const char* type_str() { return "<uint32_t>"; }
+};
+
+// Test vst[_m] instructions for correct pointer update and store result.
+template <typename T, bool post_increment, bool stripmine>
+void test_ldst_x() {
+ uint8_t read_data[4 * VLENB] __attribute__((aligned(64)));
+ T* input = reinterpret_cast<T*>(read_data);
+ constexpr int size = (stripmine ? 4 : 1) * VLENB / sizeof(T);
+ for (int i = 0; i < size; i++) {
+ input[i] = static_cast<T>(i);
+ }
+
+ if (stripmine) {
+ vld_x_m(T, v0, input);
+ } else {
+ vld_x(T, v0, input);
+ }
+
+ uint8_t write_data[4 * VLENB] __attribute__((aligned(64)));
+ memset(write_data, 0, sizeof(write_data));
+ T* dut = reinterpret_cast<T*>(write_data);
+ if (post_increment) {
+ if (stripmine) {
+ dut = vstpm_data(dut);
+ } else {
+ dut = vstp_data(dut);
+ }
+ } else {
+ vst_x(T, v0, dut);
+ }
+
+ // Test post increment
+ int offset = 0;
+ if (post_increment) {
+ offset = (stripmine ? 4 : 1) * VLENB;
+ }
+ void* target = reinterpret_cast<void*>(write_data + offset);
+ if (reinterpret_cast<void*>(dut) != target) {
+ printf("Failed test_ldst_x for type %s:\n", TypeString<T>::type_str());
+ printf(" expected dut=%p to be %p\n", reinterpret_cast<void*>(dut),
+ target);
+ exit(1);
+ }
+
+ dut = reinterpret_cast<T*>(write_data);
+ for (int i = 0; i < size; i++) {
+ if (dut[i] != static_cast<T>(i)) {
+ printf("Failed test_ldst_x for type %s:\n", TypeString<T>::type_str());
+ printf(" expected %d at position %d/%d got ", i, i, size);
+ printf(PrintfTraits<T>::kFmt, dut[i]);
+ printf("\n");
+ exit(1);
+ }
+ }
+}
+
+// Test vst_p[_m] instructions for correct pointer update and store result.
+template <typename T, bool stripmine>
+void test_ldst_p_xx(int length) {
+ uint8_t read_data[4 * VLENB] __attribute__((aligned(64)));
+ T* input = reinterpret_cast<T*>(read_data);
+ constexpr int size = (stripmine ? 4 : 1) * VLENB / sizeof(T);
+ for (int i = 0; i < size; i++) {
+ input[i] = static_cast<T>(i);
+ }
+
+ if (stripmine) {
+ vld_x_m(T, v0, input);
+ } else {
+ vld_x(T, v0, input);
+ }
+
+ uint8_t write_data[4 * VLENB] __attribute__((aligned(64)));
+ memset(write_data, 0, sizeof(write_data));
+ T* dut = reinterpret_cast<T*>(write_data);
+ if (stripmine) {
+ dut = vstpm_xx(dut, length);
+ } else {
+ dut = vstp_xx(dut, length);
+ }
+
+ // Test post increment
+ void* target = reinterpret_cast<void*>(write_data + length * sizeof(T));
+ if (reinterpret_cast<void*>(dut) != target) {
+ printf("Failed test_ldst_p_xx for type %s:\n", TypeString<T>::type_str());
+ printf(" expected dut=%p to be %p\n", reinterpret_cast<void*>(dut),
+ target);
+ exit(1);
+ }
+
+ dut = reinterpret_cast<T*>(write_data);
+ for (int i = 0; i < size; i++) {
+ if (dut[i] != static_cast<T>(i)) {
+ printf("Failed test_ldst_p_xx for type %s:\n", TypeString<T>::type_str());
+ printf(" expected %d at position %d/%d got ", i, i, size);
+ printf(PrintfTraits<T>::kFmt, dut[i]);
+ printf("\n");
+ exit(1);
+ }
+ }
+}
+
+// Test vst_s[p][_m] instructions for correct pointer update and store result.
+template <typename T, bool post_increment, bool stripmine>
+void test_ldst_s_xx(int stride) {
+ uint8_t read_data[4 * VLENB] __attribute__((aligned(64)));
+ T* input = reinterpret_cast<T*>(read_data);
+ constexpr int size = (stripmine ? 4 : 1) * VLENB / sizeof(T);
+ for (int i = 0; i < size; i++) {
+ input[i] = static_cast<T>(i);
+ }
+
+ if (stripmine) {
+ vld_x_m(T, v0, input);
+ } else {
+ vld_x(T, v0, input);
+ }
+
+ uint8_t write_data[9 * VLENB] __attribute__((aligned(64)));
+ memset(write_data, 0, sizeof(write_data));
+ T* dut = reinterpret_cast<T*>(write_data);
+ if (post_increment) {
+ if (stripmine) {
+ dut = vstspm_xx(dut, stride);
+ } else {
+ dut = vstsp_xx(dut, stride);
+ }
+ } else {
+ if (stripmine) {
+ vst_s_xx_m(T, v0, dut, stride);
+ } else {
+ vst_s_xx(T, v0, dut, stride);
+ }
+ }
+
+ // Test post increment
+ int offset = 0;
+ if (post_increment) {
+ offset = (stripmine ? 4 * stride : stride) * sizeof(T);
+ }
+ void* target = reinterpret_cast<void*>(write_data + offset);
+ if (reinterpret_cast<void*>(dut) != target) {
+ printf("Failed test_ldst_s_xx for type %s:\n", TypeString<T>::type_str());
+ printf(" expected dut=%p to be %p\n", reinterpret_cast<void*>(dut),
+ target);
+ exit(1);
+ }
+
+ dut = reinterpret_cast<T*>(write_data);
+ constexpr int num_vectors = stripmine ? 4 : 1;
+ int val = 0;
+ for (int v = 0; v < num_vectors; ++v) {
+ for (size_t i = 0; i < VLENB / sizeof(T); i++) {
+ if (dut[i] != static_cast<T>(val)) {
+ printf("Failed test_ldst_s_xx for type %s:\n",
+ TypeString<T>::type_str());
+ printf(" expected %d at position %d/%d got ", val,
+ v * VLENB / sizeof(T) + i, size);
+ printf(PrintfTraits<T>::kFmt, dut[i]);
+ printf("\n");
+ exit(1);
+ }
+ val++;
+ }
+ dut += stride;
+ }
+}
+
+// Test vst_l[p][_m] instructions for correct pointer update and store result.
+template <typename T, bool post_increment, bool stripmine>
+void test_ldst_l_xx(int length) {
+ uint8_t read_data[4 * VLENB] __attribute__((aligned(64)));
+ T* input = reinterpret_cast<T*>(read_data);
+ constexpr int size = (stripmine ? 4 : 1) * VLENB / sizeof(T);
+ for (int i = 0; i < size; i++) {
+ input[i] = static_cast<T>(i);
+ }
+
+ // Saturate length
+ length = std::min(size, length);
+
+ if (stripmine) {
+ vld_x_m(T, v0, input);
+ } else {
+ vld_x(T, v0, input);
+ }
+
+ uint8_t write_data[4 * VLENB] __attribute__((aligned(64)));
+ memset(write_data, 0, sizeof(write_data));
+ T* dut = reinterpret_cast<T*>(write_data);
+ if (post_increment) {
+ if (stripmine) {
+ dut = vstlpm_xx(dut, length);
+ } else {
+ dut = vstlp_xx(dut, length);
+ }
+ } else {
+ if (stripmine) {
+ vst_l_xx_m(T, v0, dut, length);
+ } else {
+ vst_l_xx(T, v0, dut, length);
+ }
+ }
+
+ // Test post increment
+ void* target = reinterpret_cast<void*>(
+ write_data + (post_increment ? length * sizeof(T) : 0));
+ if (reinterpret_cast<void*>(dut) != target) {
+ printf("Failed test_ldst_l_xx for type %s:\n", TypeString<T>::type_str());
+ printf(" expected dut=%p to be %p\n", reinterpret_cast<void*>(dut),
+ target);
+ exit(1);
+ }
+
+ dut = reinterpret_cast<T*>(write_data);
+ for (int i = 0; i < length; i++) {
+ if (dut[i] != static_cast<T>(i)) {
+ printf("Failed test_ldst_l_xx for type %s:\n", TypeString<T>::type_str());
+ printf(" expected %d at position %d/%d got ", i, i, size);
+ printf(PrintfTraits<T>::kFmt, dut[i]);
+ printf("\n");
+ exit(1);
+ }
+ }
+}
+
+// Test vst_tp[_m] instructions for correct pointer update and store result.
+template <typename T, bool stripmine>
+void test_ldst_tp_xx(int stride) {
+ uint8_t read_data[4 * VLENB] __attribute__((aligned(64)));
+ T* input = reinterpret_cast<T*>(read_data);
+ constexpr int size = (stripmine ? 4 : 1) * VLENB / sizeof(T);
+ for (int i = 0; i < size; i++) {
+ input[i] = static_cast<T>(i);
+ }
+
+ if (stripmine) {
+ vld_x_m(T, v0, input);
+ } else {
+ vld_x(T, v0, input);
+ }
+
+ uint8_t write_data[9 * VLENB] __attribute__((aligned(64)));
+ memset(write_data, 0, sizeof(write_data));
+ T* dut = reinterpret_cast<T*>(write_data);
+
+ if (stripmine) {
+ dut = vsttpm_xx(dut, stride);
+ } else {
+ dut = vsttp_xx(dut, stride);
+ }
+
+ // Test post increment
+ void* target = reinterpret_cast<void*>(write_data + VLENB);
+ if (reinterpret_cast<void*>(dut) != target) {
+ printf("Failed test_ldst_tp_xx for type %s:\n", TypeString<T>::type_str());
+ printf(" expected dut=%p to be %p\n", reinterpret_cast<void*>(dut),
+ target);
+ exit(1);
+ }
+
+ dut = reinterpret_cast<T*>(write_data);
+ constexpr int num_vectors = stripmine ? 4 : 1;
+ int val = 0;
+ for (int v = 0; v < num_vectors; ++v) {
+ for (size_t i = 0; i < VLENB / sizeof(T); i++) {
+ if (dut[i] != static_cast<T>(val)) {
+ printf("Failed test_ldst_tp_xx for type %s:\n",
+ TypeString<T>::type_str());
+ printf(" expected %d at position %d/%d got ", val,
+ v * VLENB / sizeof(T) + i, size);
+ printf(PrintfTraits<T>::kFmt, dut[i]);
+ printf("\n");
+ exit(1);
+ }
+ val++;
+ }
+ dut += stride;
+ }
+}
+
+template <typename T, bool sm>
+void test_vst_l() {
+ constexpr int n = sizeof(T) * 8;
+ constexpr int s = sm ? 4 : 1;
+ constexpr int size = s * VLEN / n + 1;
+ T in[size] __attribute__((aligned(64)));
+ T dut[size] __attribute__((aligned(64)));
+ int vlen;
+ if (sm) {
+ getmaxvl_m(T, vlen);
+ } else {
+ getmaxvl(T, vlen);
+ }
+
+ for (int j = 0; j <= vlen + 1; ++j) {
+ in[j] = j + 1;
+ }
+
+ if (sm) {
+ vdup_x_m(T, v4, 0xcc);
+ vld_x_m(T, v0, in);
+ vst_x_m(T, v4, dut);
+ vst_x_m(T, v4, dut + vlen);
+ } else {
+ vdup_x(T, v1, 0xcc);
+ vld_x(T, v0, in);
+ vst_x(T, v1, dut);
+ vst_x(T, v1, dut + vlen);
+ }
+
+ for (int i = 0; i <= vlen; ++i) {
+ if (sm) {
+ vst_x_m(T, v4, dut);
+ vst_l_xx_m(T, v0, dut, i);
+ } else {
+ vst_x(T, v1, dut);
+ vst_l_xx(T, v0, dut, i);
+ }
+ for (int j = 0; j <= vlen; ++j) {
+ T ref = j < i ? j + 1 : 0xcc;
+ if (ref != dut[j]) {
+ printf("**error vst_l[%d,%d] ", i, j);
+ printf(PrintfTraits<T>::kFmtHex, ref);
+ printf(" ");
+ printf(PrintfTraits<T>::kFmtHex, dut[j]);
+ printf("\n");
+ exit(-1);
+ }
+ }
+ }
+}
+
+template <typename T>
+void test_vst_s() {
+ constexpr int n = sizeof(T) * 8;
+ constexpr int size = 4 * VLEN / n;
+ T in[size] __attribute__((aligned(64)));
+ T dut[2 * size] __attribute__((aligned(64)));
+ int vlen;
+ getmaxvl(T, vlen);
+
+ for (int i = 0; i < 2 * size; ++i) {
+ dut[i] = T(0xcccccccc);
+ }
+
+ for (int i = 0; i < 4 * vlen; ++i) {
+ in[i] = i + 1;
+ }
+
+ vld_x_m(T, v0, in);
+ vst_s_xx_m(T, v0, dut, vlen + 2);
+
+ for (int s = 0; s < 4; ++s) {
+ T* d = dut + s * (vlen + 2);
+ for (int i = 0; i < vlen + 2; ++i) {
+ T ref = i < vlen ? i + 1 + s * vlen : T(0xcccccccc);
+ if (ref != d[i]) {
+ printf("**error vst_s[%d] ", i);
+ printf(PrintfTraits<T>::kFmtHex, ref);
+ printf(" ");
+ printf(PrintfTraits<T>::kFmtHex, d[i]);
+ printf("\n");
+ exit(-1);
+ }
+ }
+ }
+}
+
+int main() {
+ int vlenb, vlenh, vlenw;
+
+ getmaxvl_b(vlenb);
+ getmaxvl_h(vlenh);
+ getmaxvl_w(vlenw);
+
+ // vst.*.x
+ test_ldst_x<uint8_t, false, false>();
+ test_ldst_x<uint16_t, false, false>();
+ test_ldst_x<uint32_t, false, false>();
+
+ // vst.*.p.x
+ test_ldst_x<uint8_t, true, false>();
+ test_ldst_x<uint16_t, true, false>();
+ test_ldst_x<uint32_t, true, false>();
+
+ // vst.*.p.x.m
+ test_ldst_x<uint8_t, true, true>();
+ test_ldst_x<uint16_t, true, true>();
+ test_ldst_x<uint32_t, true, true>();
+
+ // vst.*.l.xx
+ test_ldst_l_xx<uint8_t, false, false>(1);
+ test_ldst_l_xx<uint16_t, false, false>(1);
+ test_ldst_l_xx<uint32_t, false, false>(1);
+ test_ldst_l_xx<uint8_t, false, false>(vlenb / 2);
+ test_ldst_l_xx<uint16_t, false, false>(vlenh / 2);
+ test_ldst_l_xx<uint32_t, false, false>(vlenw / 2);
+ test_ldst_l_xx<uint8_t, false, false>(vlenb - 1);
+ test_ldst_l_xx<uint16_t, false, false>(vlenh - 1);
+ test_ldst_l_xx<uint32_t, false, false>(vlenw - 1);
+ test_ldst_l_xx<uint8_t, false, false>(vlenb);
+ test_ldst_l_xx<uint16_t, false, false>(vlenh);
+ test_ldst_l_xx<uint32_t, false, false>(vlenw);
+ test_ldst_l_xx<uint8_t, false, false>(vlenb + 1);
+ test_ldst_l_xx<uint16_t, false, false>(vlenh + 1);
+ test_ldst_l_xx<uint32_t, false, false>(vlenw + 1);
+
+ // vst.*.lp.xx
+ test_ldst_l_xx<uint8_t, true, false>(1);
+ test_ldst_l_xx<uint16_t, true, false>(1);
+ test_ldst_l_xx<uint32_t, true, false>(1);
+ test_ldst_l_xx<uint8_t, true, false>(vlenb / 2);
+ test_ldst_l_xx<uint16_t, true, false>(vlenh / 2);
+ test_ldst_l_xx<uint32_t, true, false>(vlenw / 2);
+ test_ldst_l_xx<uint8_t, true, false>(vlenb - 1);
+ test_ldst_l_xx<uint16_t, true, false>(vlenh - 1);
+ test_ldst_l_xx<uint32_t, true, false>(vlenw - 1);
+ test_ldst_l_xx<uint8_t, true, false>(vlenb);
+ test_ldst_l_xx<uint16_t, true, false>(vlenh);
+ test_ldst_l_xx<uint32_t, true, false>(vlenw);
+ test_ldst_l_xx<uint8_t, true, false>(vlenb + 1);
+ test_ldst_l_xx<uint16_t, true, false>(vlenh + 1);
+ test_ldst_l_xx<uint32_t, true, false>(vlenw + 1);
+
+ // vst.*.p.xx
+ test_ldst_p_xx<uint8_t, false>(1);
+ test_ldst_p_xx<uint16_t, false>(1);
+ test_ldst_p_xx<uint32_t, false>(1);
+ test_ldst_p_xx<uint8_t, false>(vlenb / 2);
+ test_ldst_p_xx<uint16_t, false>(vlenh / 2);
+ test_ldst_p_xx<uint32_t, false>(vlenw / 2);
+ test_ldst_p_xx<uint8_t, false>(vlenb - 1);
+ test_ldst_p_xx<uint16_t, false>(vlenh - 1);
+ test_ldst_p_xx<uint32_t, false>(vlenw - 1);
+ test_ldst_p_xx<uint8_t, false>(vlenb);
+ test_ldst_p_xx<uint16_t, false>(vlenh);
+ test_ldst_p_xx<uint32_t, false>(vlenw);
+ test_ldst_p_xx<uint8_t, false>(vlenb + 1);
+ test_ldst_p_xx<uint16_t, false>(vlenh + 1);
+ test_ldst_p_xx<uint32_t, false>(vlenw + 1);
+
+ // vst.*.sp.xx. Stride should be >= vector size.
+ test_ldst_s_xx<uint8_t, true, false>(vlenb);
+ test_ldst_s_xx<uint16_t, true, false>(vlenh);
+ test_ldst_s_xx<uint32_t, true, false>(vlenw);
+ test_ldst_s_xx<uint8_t, true, false>(vlenb + 1);
+ test_ldst_s_xx<uint16_t, true, false>(vlenh + 1);
+ test_ldst_s_xx<uint32_t, true, false>(vlenw + 1);
+
+ // vst.*.tp.xx. Stride should be >= vector size.
+ test_ldst_tp_xx<uint8_t, false>(vlenb);
+ test_ldst_tp_xx<uint16_t, false>(vlenh);
+ test_ldst_tp_xx<uint32_t, false>(vlenw);
+ test_ldst_tp_xx<uint8_t, false>(vlenb + 1);
+ test_ldst_tp_xx<uint16_t, false>(vlenh + 1);
+ test_ldst_tp_xx<uint32_t, false>(vlenw + 1);
+
+ getmaxvl_b_m(vlenb);
+ getmaxvl_h_m(vlenh);
+ getmaxvl_w_m(vlenw);
+
+ // vst.*.l.xx.m
+ test_ldst_l_xx<uint8_t, false, true>(1);
+ test_ldst_l_xx<uint16_t, false, true>(1);
+ test_ldst_l_xx<uint32_t, false, true>(1);
+ test_ldst_l_xx<uint8_t, false, true>(vlenb / 2);
+ test_ldst_l_xx<uint16_t, false, true>(vlenh / 2);
+ test_ldst_l_xx<uint32_t, false, true>(vlenw / 2);
+ test_ldst_l_xx<uint8_t, false, true>(vlenb - 1);
+ test_ldst_l_xx<uint16_t, false, true>(vlenh - 1);
+ test_ldst_l_xx<uint32_t, false, true>(vlenw - 1);
+ test_ldst_l_xx<uint8_t, false, true>(vlenb);
+ test_ldst_l_xx<uint16_t, false, true>(vlenh);
+ test_ldst_l_xx<uint32_t, false, true>(vlenw);
+ test_ldst_l_xx<uint8_t, false, true>(vlenb + 1);
+ test_ldst_l_xx<uint16_t, false, true>(vlenh + 1);
+ test_ldst_l_xx<uint32_t, false, true>(vlenw + 1);
+
+ // vst.*.lp.xx.m
+ test_ldst_l_xx<uint8_t, true, true>(1);
+ test_ldst_l_xx<uint16_t, true, true>(1);
+ test_ldst_l_xx<uint32_t, true, true>(1);
+ test_ldst_l_xx<uint8_t, true, true>(vlenb / 2);
+ test_ldst_l_xx<uint16_t, true, true>(vlenh / 2);
+ test_ldst_l_xx<uint32_t, true, true>(vlenw / 2);
+ test_ldst_l_xx<uint8_t, true, true>(vlenb - 1);
+ test_ldst_l_xx<uint16_t, true, true>(vlenh - 1);
+ test_ldst_l_xx<uint32_t, true, true>(vlenw - 1);
+ test_ldst_l_xx<uint8_t, true, true>(vlenb);
+ test_ldst_l_xx<uint16_t, true, true>(vlenh);
+ test_ldst_l_xx<uint32_t, true, true>(vlenw);
+ test_ldst_l_xx<uint8_t, true, true>(vlenb + 1);
+ test_ldst_l_xx<uint16_t, true, true>(vlenh + 1);
+ test_ldst_l_xx<uint32_t, true, true>(vlenw + 1);
+
+ // vst.*.p.xx.m
+ test_ldst_p_xx<uint8_t, true>(vlenb);
+ test_ldst_p_xx<uint16_t, true>(vlenh);
+ test_ldst_p_xx<uint32_t, true>(vlenw);
+ test_ldst_p_xx<uint8_t, true>(vlenb + 1);
+ test_ldst_p_xx<uint16_t, true>(vlenh + 1);
+ test_ldst_p_xx<uint32_t, true>(vlenw + 1);
+
+ // vst.*.s.xx.m. Stride should be >= vector size.
+ test_ldst_s_xx<uint8_t, false, true>(vlenb);
+ test_ldst_s_xx<uint16_t, false, true>(vlenh);
+ test_ldst_s_xx<uint32_t, false, true>(vlenw);
+ test_ldst_s_xx<uint8_t, false, true>(vlenb + 1);
+ test_ldst_s_xx<uint16_t, false, true>(vlenh + 1);
+ test_ldst_s_xx<uint32_t, false, true>(vlenw + 1);
+
+ // vst.*.sp.xx.m. Stride should be >= vector size.
+ test_ldst_s_xx<uint8_t, true, true>(vlenb);
+ test_ldst_s_xx<uint16_t, true, true>(vlenh);
+ test_ldst_s_xx<uint32_t, true, true>(vlenw);
+ test_ldst_s_xx<uint8_t, true, true>(vlenb + 1);
+ test_ldst_s_xx<uint16_t, true, true>(vlenh + 1);
+ test_ldst_s_xx<uint32_t, true, true>(vlenw + 1);
+
+ // vst.*.tp.xx.m. Stride should be >= vector size.
+ test_ldst_tp_xx<uint8_t, true>(vlenb);
+ test_ldst_tp_xx<uint16_t, true>(vlenh);
+ test_ldst_tp_xx<uint32_t, true>(vlenw);
+ test_ldst_tp_xx<uint8_t, true>(vlenb + 1);
+ test_ldst_tp_xx<uint16_t, true>(vlenh + 1);
+ test_ldst_tp_xx<uint32_t, true>(vlenw + 1);
+
+ test_vst_l<uint8_t, 0>();
+ test_vst_l<uint16_t, 0>();
+ test_vst_l<uint32_t, 0>();
+
+ test_vst_l<uint8_t, 1>();
+ test_vst_l<uint16_t, 1>();
+ test_vst_l<uint32_t, 1>();
+
+ test_vst_s<uint8_t>();
+ test_vst_s<uint16_t>();
+ test_vst_s<uint32_t>();
+
+ return 0;
+}