Merge "Update crt0 and matcha.ld to support IREE."
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c4b0d6a..00c9c8d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,10 +1,13 @@
 
-cmake_minimum_required (VERSION 3.1)
+cmake_minimum_required (VERSION 3.10)
 
 set(CMAKE_C_ABI_COMPILED ON)
 set(CMAKE_CXX_ABI_COMPILED ON)
 
 set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/cmake/riscv_baremetal.cmake")
+list(APPEND CMAKE_MODULE_PATH
+  ${CMAKE_CURRENT_LIST_DIR}/cmake/
+)
 
 project(springbok_project)
 
@@ -19,13 +22,18 @@
 
 set(LINKER_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/springbok/matcha.ld")
 
+include(vec_cc_binary)
+include(vec_cc_test)
+
 add_subdirectory(springbok)
 add_subdirectory(hello_vec)
+
 add_subdirectory(vector_tests)
-add_subdirectory(vector_load_tests)
+add_subdirectory(vector_load_store_tests)
 add_subdirectory(vector_vadd_vsub_tests)
 add_subdirectory(vector_executive)
 add_subdirectory(vector_vset_tests)
+
 add_subdirectory(pw_unit_test_demo)
 
-add_subdirectory(test_vsetvl)
+add_subdirectory(tests)
\ No newline at end of file
diff --git a/cmake/riscv_baremetal.cmake b/cmake/riscv_baremetal.cmake
index 62e6c5a..9c8b93b 100644
--- a/cmake/riscv_baremetal.cmake
+++ b/cmake/riscv_baremetal.cmake
@@ -40,3 +40,16 @@
 set( CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "" )
 set( CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "" )
 set( CMAKE_EXE_LINKER_FLAGS   "${CMAKE_EXE_LINKER_FLAGS}  -nostartfiles   " )
+set( VEC_DEFAULT_COPTS
+    "-Wall"
+    "-Werror"
+    "-O0"
+    "-g3"
+    "-ggdb"
+    "-ffreestanding"
+    "-ffunction-sections"
+    "-fstack-usage"
+    "-mstrict-align"
+)
+
+set( VEC_DEFAULT_LINKOPTS -specs=nano.specs -Wl,--gc-sections -Wl,--print-memory-usage -Wl,-Map=${PROJECT_NAME}.map)
\ No newline at end of file
diff --git a/cmake/vec_cc_binary.cmake b/cmake/vec_cc_binary.cmake
new file mode 100644
index 0000000..97fd63c
--- /dev/null
+++ b/cmake/vec_cc_binary.cmake
@@ -0,0 +1,40 @@
+function(vec_cc_binary)
+  cmake_parse_arguments(
+    _RULE
+    ""
+    "NAME"
+    "SRCS;COPTS;DEFINES;LINKOPTS;DATA;DEPS;LABELS"
+    ${ARGN}
+  )
+
+set(_NAME "${_RULE_NAME}")
+project(${_RULE_NAME})
+set (CMAKE_CXX_STANDARD 17)
+
+set(_ELF_NAME "${_RULE_NAME}.elf")
+add_executable(${_ELF_NAME})
+target_include_directories(${_ELF_NAME} PUBLIC include)
+set_target_properties(${_ELF_NAME} PROPERTIES LINK_DEPENDS "${LINKER_SCRIPT}")
+
+target_sources(${_ELF_NAME}
+    PRIVATE
+      ${_RULE_SRCS}
+)
+
+target_link_libraries(${_ELF_NAME}
+    PUBLIC
+      ${_RULE_DEPS}
+)
+
+target_compile_options(${_ELF_NAME}
+    PUBLIC
+        ${VEC_DEFAULT_COPTS}
+        ${_RULE_COPTS}
+)
+
+target_link_options(${_ELF_NAME}
+    PUBLIC
+      ${_RULE_LINKOPTS}
+      ${VEC_DEFAULT_LINKOPTS}
+)
+endfunction()
diff --git a/cmake/vec_cc_test.cmake b/cmake/vec_cc_test.cmake
new file mode 100644
index 0000000..332a085
--- /dev/null
+++ b/cmake/vec_cc_test.cmake
@@ -0,0 +1,29 @@
+function(vec_cc_test)
+  cmake_parse_arguments(
+    _RULE
+    ""
+    "NAME"
+    "SRCS;COPTS;DEFINES;LINKOPTS;DATA;DEPS;LABELS"
+    ${ARGN}
+  )
+
+set(_NAME "${_RULE_NAME}")
+project(${_RULE_NAME})
+set (CMAKE_CXX_STANDARD 17)
+
+vec_cc_binary(
+  NAME
+    ${_RULE_NAME}
+  SRCS
+    ${_RULE_SRCS}
+  DEPS
+      pw_unit_test
+      pw_unit_test.main
+      pw_assert_basic
+      test_v_helpers
+      ${_RULE_DEPS}
+  LINKOPTS
+    ${_RULE_LINKOPTS}
+)
+
+endfunction()
diff --git a/hello_vec/CMakeLists.txt b/hello_vec/CMakeLists.txt
index 59efb80..4f84c45 100644
--- a/hello_vec/CMakeLists.txt
+++ b/hello_vec/CMakeLists.txt
@@ -1,35 +1,10 @@
-cmake_minimum_required(VERSION 3.10)
-
-project(hello_vec)
-
-set(TARGET hello_vec)
-set(ELF ${TARGET}.elf)
-
-add_executable(${ELF} main.cpp)
-
-target_include_directories(${ELF} PUBLIC include)
-
-set_target_properties(${ELF} PROPERTIES LINK_DEPENDS "${LINKER_SCRIPT}")
-
-target_link_libraries(${ELF} springbok)
-
-set_target_properties(
-	${ELF}
-	PROPERTIES
-	LINK_FLAGS
-     "-specs=nano.specs \
-    -Wl,--gc-sections \
-    -Wl,--print-memory-usage \
-    -Wl,-Map=${PROJECT_NAME}.map \
-    -T${LINKER_SCRIPT}")
-
-target_compile_options(${ELF} PUBLIC
-    -Wall
-    -Werror
-    -O3
-    -g3
-    -ggdb
-    -ffreestanding
-    -ffunction-sections
-    -fstack-usage
-    -mstrict-align)
+vec_cc_binary(
+    NAME
+      hello_vec
+    SRCS
+      main.cpp
+  DEPS
+    springbok
+  LINKOPTS
+    -T${LINKER_SCRIPT}
+)
\ No newline at end of file
diff --git a/pw_unit_test_demo/CMakeLists.txt b/pw_unit_test_demo/CMakeLists.txt
index 3bfaee0..b690644 100644
--- a/pw_unit_test_demo/CMakeLists.txt
+++ b/pw_unit_test_demo/CMakeLists.txt
@@ -1,42 +1,12 @@
-cmake_minimum_required(VERSION 3.10)
 
-project(pw_unit_test_demo)
-set (CMAKE_CXX_STANDARD 17)
-
-set(TARGET pw_unit_test_demo)
-set(ELF ${TARGET}.elf)
-
-add_executable(${ELF} ${TARGET}.cpp)
-
-target_include_directories(${ELF} PUBLIC include)
-
-set_target_properties(${ELF} PROPERTIES LINK_DEPENDS "${LINKER_SCRIPT}")
-
-
-target_link_libraries(${ELF} springbok)
-target_link_libraries(${ELF} pw_unit_test)
-target_link_libraries(${ELF} pw_unit_test.main)
-target_link_libraries(${ELF} pw_assert_basic)
-
-
-set_target_properties(
-    ${ELF}
-    PROPERTIES
-    LINK_FLAGS
-     "-specs=nano.specs \
-    -Wl,--gc-sections \
-    -Wl,--print-memory-usage \
-    -Wl,-Map=${PROJECT_NAME}.map \
-    -T${LINKER_SCRIPT} \
-    -Xlinker --defsym=__itcm_length__=256K")
-
-target_compile_options(${ELF} PUBLIC
-    -Wall
-    -Werror
-    -O3
-    -g3
-    -ggdb
-    -ffreestanding
-    -ffunction-sections
-    -fstack-usage
-    -mstrict-align)
+vec_cc_test(
+  NAME
+    pw_unit_test_demo
+  SRCS
+    pw_unit_test_demo.cpp
+  DEPS
+    springbok
+  LINKOPTS
+   -T${LINKER_SCRIPT}
+   -Xlinker --defsym=__itcm_length__=128K
+)
diff --git a/springbok/CMakeLists.txt b/springbok/CMakeLists.txt
index 41acb68..0ba73f6 100644
--- a/springbok/CMakeLists.txt
+++ b/springbok/CMakeLists.txt
@@ -1,34 +1,29 @@
-cmake_minimum_required(VERSION 3.1)
 
 enable_language(ASM)
 
 add_library(springbok INTERFACE)
 add_library(springbok_intrinsic STATIC)
-target_sources(springbok_intrinsic PRIVATE
-    crt0.s
-    springbok_gloss.cpp)
+target_sources(springbok_intrinsic
+    PRIVATE
+      crt0.s
+      springbok_gloss.cpp
+)
 
 target_include_directories(springbok_intrinsic PUBLIC include)
 
 target_link_libraries(springbok
 INTERFACE
-    springbok_intrinsic
+  springbok_intrinsic
 )
 
 target_include_directories(springbok INTERFACE include)
 
-target_compile_options(springbok_intrinsic PUBLIC
-    -Wall
-    -Werror
-    -Os
-    -g3
-    -ggdb
-    -ffreestanding
-    -ffunction-sections
-    -fstack-usage
-    -mstrict-align)
+target_compile_options(springbok_intrinsic
+    PUBLIC
+      ${VEC_DEFAULT_COPTS}
+)
 
 target_link_options(springbok
-INTERFACE
--Wl,--whole-archive ${CMAKE_CURRENT_BINARY_DIR}/libspringbok_intrinsic.a -Wl,--no-whole-archive
+    INTERFACE
+      -Wl,--whole-archive ${CMAKE_CURRENT_BINARY_DIR}/libspringbok_intrinsic.a -Wl,--no-whole-archive
 )
diff --git a/test_vsetvl/CMakeLists.txt b/test_vsetvl/CMakeLists.txt
deleted file mode 100644
index cd7a075..0000000
--- a/test_vsetvl/CMakeLists.txt
+++ /dev/null
@@ -1,42 +0,0 @@
-cmake_minimum_required(VERSION 3.10)
-
-project(test_vsetvl)
-set (CMAKE_CXX_STANDARD 17)
-
-set(TARGET test_vsetvl)
-set(ELF ${TARGET}.elf)
-
-add_executable(${ELF} ${TARGET}.cpp)
-
-target_include_directories(${ELF} PUBLIC include)
-
-set_target_properties(${ELF} PROPERTIES LINK_DEPENDS "${LINKER_SCRIPT}")
-
-
-target_link_libraries(${ELF} springbok)
-target_link_libraries(${ELF} pw_unit_test)
-target_link_libraries(${ELF} pw_unit_test.main)
-target_link_libraries(${ELF} pw_assert_basic)
-
-
-set_target_properties(
-    ${ELF}
-    PROPERTIES
-    LINK_FLAGS
-     "-specs=nano.specs \
-    -Wl,--gc-sections \
-    -Wl,--print-memory-usage \
-    -Wl,-Map=${PROJECT_NAME}.map \
-    -T${LINKER_SCRIPT} \
-    -Xlinker --defsym=__itcm_length__=256K")
-
-target_compile_options(${ELF} PUBLIC
-    -Wall
-    -Werror
-    -O3
-    -g3
-    -ggdb
-    -ffreestanding
-    -ffunction-sections
-    -fstack-usage
-    -mstrict-align)
diff --git a/test_vsetvl/test_vsetvl.cpp b/test_vsetvl/test_vsetvl.cpp
deleted file mode 100644
index 8eb5912..0000000
--- a/test_vsetvl/test_vsetvl.cpp
+++ /dev/null
@@ -1,160 +0,0 @@
-#include <riscv_vector.h>
-#include <springbok_intrinsics.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "pw_unit_test/framework.h"
-
-namespace test_vsetvl {
-namespace {
-
-const uint64_t VLEN = 512u;
-const uint64_t ELEN = 32u;
-
-uint32_t AVLS[] = {1,    2,    3,     4,     5,     8,    16,   17,
-                   32,   36,   55,    64,    100,   128,  256,  321,
-                   512,  623,  1024,  1100,  1543,  2048, 3052, 4096,
-                   5555, 8192, 10241, 16384, 24325, 32768};
-const int32_t AVL_COUNT = sizeof(AVLS) / sizeof(AVLS[0]);
-
-#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
-
-static uint32_t calculate_vl(uint32_t sew, uint32_t avl, float lmul) {
-  uint32_t vlmax = (uint32_t)(VLEN * lmul / sew);
-  return MIN(avl, vlmax);
-}
-
-TEST(VsetvlTest, vsetvl_e8m1) {
-  for (int i = 0; i < AVL_COUNT; i++) {
-    size_t vl = vsetvl_e8m1(AVLS[i]);
-    EXPECT_EQ(vl, calculate_vl(8, AVLS[i], 1.0));
-  }
-}
-
-TEST(VsetvlTest, vsetvl_e16m1) {
-  for (int i = 0; i < AVL_COUNT; i++) {
-    size_t vl = vsetvl_e16m1(AVLS[i]);
-    EXPECT_EQ(vl, calculate_vl(16, AVLS[i], 1.0));
-  }
-}
-
-TEST(VsetvlTest, vsetvl_e32m1) {
-  for (int i = 0; i < AVL_COUNT; i++) {
-    size_t vl = vsetvl_e32m1(AVLS[i]);
-    EXPECT_EQ(vl, calculate_vl(32, AVLS[i], 1.0));
-  }
-}
-
-TEST(VsetvlTest, vsetvl_e8m2) {
-  for (int i = 0; i < AVL_COUNT; i++) {
-    size_t vl = vsetvl_e8m2(AVLS[i]);
-    EXPECT_EQ(vl, calculate_vl(8, AVLS[i], 2.0));
-  }
-}
-
-TEST(VsetvlTest, vsetvl_e16m2) {
-  for (int i = 0; i < AVL_COUNT; i++) {
-    size_t vl = vsetvl_e16m2(AVLS[i]);
-    EXPECT_EQ(vl, calculate_vl(16, AVLS[i], 2.0));
-  }
-}
-
-TEST(VsetvlTest, vsetvl_e32m2) {
-  for (int i = 0; i < AVL_COUNT; i++) {
-    size_t vl = vsetvl_e32m2(AVLS[i]);
-    EXPECT_EQ(vl, calculate_vl(32, AVLS[i], 2.0));
-  }
-}
-
-TEST(VsetvlTest, vsetvl_e8m4) {
-  for (int i = 0; i < AVL_COUNT; i++) {
-    size_t vl = vsetvl_e8m4(AVLS[i]);
-    EXPECT_EQ(vl, calculate_vl(8, AVLS[i], 4.0));
-  }
-}
-
-TEST(VsetvlTest, vsetvl_e16m4) {
-  for (int i = 0; i < AVL_COUNT; i++) {
-    size_t vl = vsetvl_e16m4(AVLS[i]);
-    EXPECT_EQ(vl, calculate_vl(16, AVLS[i], 4.0));
-  }
-}
-
-TEST(VsetvlTest, vsetvl_e32m4) {
-  for (int i = 0; i < AVL_COUNT; i++) {
-    size_t vl = vsetvl_e32m4(AVLS[i]);
-    EXPECT_EQ(vl, calculate_vl(32, AVLS[i], 4.0));
-  }
-}
-
-TEST(VsetvlTest, vsetvl_e8m8) {
-  for (int i = 0; i < AVL_COUNT; i++) {
-    size_t vl = vsetvl_e8m8(AVLS[i]);
-    EXPECT_EQ(vl, calculate_vl(8, AVLS[i], 8.0));
-  }
-}
-
-TEST(VsetvlTest, vsetvl_e16m8) {
-  for (int i = 0; i < AVL_COUNT; i++) {
-    size_t vl = vsetvl_e16m8(AVLS[i]);
-    EXPECT_EQ(vl, calculate_vl(16, AVLS[i], 8.0));
-  }
-}
-
-TEST(VsetvlTest, vsetvl_e32m8) {
-  for (int i = 0; i < AVL_COUNT; i++) {
-    size_t vl = vsetvl_e32m8(AVLS[i]);
-    EXPECT_EQ(vl, calculate_vl(32, AVLS[i], 8.0));
-  }
-}
-
-TEST(VsetvlTest, vsetvlmax_e8m1) {
-  EXPECT_EQ(vsetvlmax_e8m1(), (int)VLEN / 8 * 1);
-}
-
-TEST(VsetvlTest, vsetvlmax_e8m2) {
-  EXPECT_EQ(vsetvlmax_e8m2(), (int)VLEN / 8 * 2);
-}
-
-TEST(VsetvlTest, vsetvlmax_e8m4) {
-  EXPECT_EQ(vsetvlmax_e8m4(), (int)VLEN / 8 * 4);
-}
-
-TEST(VsetvlTest, vsetvlmax_e8m8) {
-  EXPECT_EQ(vsetvlmax_e8m8(), (int)VLEN / 8 * 8);
-}
-
-TEST(VsetvlTest, vsetvlmax_e16m1) {
-  EXPECT_EQ(vsetvlmax_e16m1(), (int)VLEN / 16 * 1);
-}
-
-TEST(VsetvlTest, vsetvlmax_e16m2) {
-  EXPECT_EQ(vsetvlmax_e16m2(), (int)VLEN / 16 * 2);
-}
-
-TEST(VsetvlTest, vsetvlmax_e16m4) {
-  EXPECT_EQ(vsetvlmax_e16m4(), (int)VLEN / 16 * 4);
-}
-
-TEST(VsetvlTest, vsetvlmax_e16m8) {
-  EXPECT_EQ(vsetvlmax_e16m8(), (int)VLEN / 16 * 8);
-}
-
-TEST(VsetvlTest, vsetvlmax_e32m1) {
-  EXPECT_EQ(vsetvlmax_e32m1(), (int)VLEN / 32 * 1);
-}
-
-TEST(VsetvlTest, vsetvlmax_e32m2) {
-  EXPECT_EQ(vsetvlmax_e32m2(), (int)VLEN / 32 * 2);
-}
-
-TEST(VsetvlTest, vsetvlmax_e32m4) {
-  EXPECT_EQ(vsetvlmax_e32m4(), (int)VLEN / 32 * 4);
-}
-
-TEST(VsetvlTest, vsetvlmax_e32m8) {
-  EXPECT_EQ(vsetvlmax_e32m8(), (int)VLEN / 32 * 8);
-}
-
-}  // namespace
-}  // namespace test_vsetvl
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644
index 0000000..fe84b42
--- /dev/null
+++ b/tests/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 3.10)
+
+enable_language(ASM)
+
+add_library(test_v_helpers
+	test_v_helpers.cpp)
+
+target_include_directories(test_v_helpers PUBLIC include)
+
+target_compile_options(test_v_helpers PUBLIC
+      ${VEC_DEFAULT_COPTS}
+)
+
+vec_cc_test(
+  NAME
+    vsetvl_test
+  SRCS
+    vsetvl_test.cpp
+  DEPS
+    springbok
+  LINKOPTS
+   -T${LINKER_SCRIPT}
+   -Xlinker --defsym=__itcm_length__=256K
+)
+
+vec_cc_test(
+  NAME
+    vle_vse_test
+  SRCS
+    vle_vse_test.cpp
+  DEPS
+    springbok
+  LINKOPTS
+   -T${LINKER_SCRIPT}
+   -Xlinker --defsym=__itcm_length__=256K
+)
diff --git a/tests/include/test_v_helpers.h b/tests/include/test_v_helpers.h
new file mode 100644
index 0000000..e8ac315
--- /dev/null
+++ b/tests/include/test_v_helpers.h
@@ -0,0 +1,44 @@
+#ifndef TEST_V_HELPERS_H
+#define TEST_V_HELPERS_H
+
+namespace test_v_helpers {
+
+enum VSEW {
+  SEW_E8 = 0,
+  SEW_E16 = 1,
+  SEW_E32 = 2,
+/* // SEW limited to E32
+  SEW_E64 = 3,
+  SEW_E128 = 4,
+  SEW_E256 = 5,
+  SEW_E512 = 6,
+  SEW_E1024 = 7,
+*/
+};
+
+enum VLMUL {
+
+/* // Fractional LMUL not supported by our intrinsic compiler
+  LMUL_MF8 = 5,
+  LMUL_MF4 = 6,
+  LMUL_MF2 = 7,
+*/
+  LMUL_M1 = 0,
+  LMUL_M2 = 1,
+  LMUL_M4 = 2,
+  LMUL_M8 = 3,
+};
+
+uint32_t get_vtype(VSEW sew, VLMUL lmul, bool tail_agnostic, bool mask_agnostic);
+
+// vsetvl  rd, rs1, rs2      # rd = new vl, rs1 = AVL, rs2 = new vtype value
+uint32_t set_vsetvl(VSEW sew, VLMUL lmul, uint32_t avl, bool tail_agnostic, bool mask_agnostic);
+
+int set_vsetvl_intrinsic(VSEW sew, VLMUL lmul, uint32_t avl);
+
+int get_vsetvlmax_intrinsic(VSEW sew, VLMUL lmul);
+
+int set_vsetvli(VSEW sew, VLMUL lmul, uint32_t avl);
+
+}
+#endif
diff --git a/tests/test_v_helpers.cpp b/tests/test_v_helpers.cpp
new file mode 100644
index 0000000..f5404e3
--- /dev/null
+++ b/tests/test_v_helpers.cpp
@@ -0,0 +1,285 @@
+#include <riscv_vector.h>
+#include "test_v_helpers.h"
+
+
+namespace test_v_helpers {
+
+uint32_t get_vtype(VSEW sew, VLMUL lmul, bool tail_agnostic,
+                   bool mask_agnostic) {
+  return (static_cast<int>(lmul) & 0x7) |
+          (static_cast<int>(sew) & 0x7) << 3 |
+          (tail_agnostic & 0x1) << 6 |
+          (mask_agnostic & 0x1) << 7;
+}
+
+uint32_t set_vsetvl(VSEW sew, VLMUL lmul, uint32_t avl, bool tail_agnostic, bool mask_agnostic) {
+  uint32_t vtype = get_vtype(sew, lmul, tail_agnostic, mask_agnostic);
+  uint32_t vl;
+  __asm__ volatile(
+    "vsetvl %[VL], %[AVL], %[VTYPE]"
+    : [VL] "=r" (vl)
+    : [AVL] "r" (avl), [VTYPE] "r" (vtype)
+  );
+  return vl;
+}
+
+int set_vsetvl_intrinsic(VSEW sew, VLMUL lmul, uint32_t avl) {
+  switch(lmul) {
+    case VLMUL::LMUL_M1:
+      switch(sew) {
+        case VSEW::SEW_E8:
+          return vsetvl_e8m1(avl);
+          break;
+        case VSEW::SEW_E16:
+          return vsetvl_e16m1(avl);
+          break;
+        case VSEW::SEW_E32:
+          return vsetvl_e32m1(avl);
+          break;
+        default:
+          return -1;
+          break;
+      }
+      break;
+    case VLMUL::LMUL_M2:
+      switch(sew) {
+        case VSEW::SEW_E8:
+          return vsetvl_e8m2(avl);
+          break;
+        case VSEW::SEW_E16:
+          return vsetvl_e16m2(avl);
+          break;
+        case VSEW::SEW_E32:
+          return vsetvl_e32m2(avl);
+          break;
+        default:
+          return -1;
+          break;
+      }
+    case VLMUL::LMUL_M4:
+      switch(sew) {
+        case VSEW::SEW_E8:
+          return vsetvl_e8m4(avl);
+          break;
+        case VSEW::SEW_E16:
+          return vsetvl_e16m4(avl);
+          break;
+        case VSEW::SEW_E32:
+          return vsetvl_e32m4(avl);
+          break;
+        default:
+          return -1;
+          break;
+      }
+      break;
+    case VLMUL::LMUL_M8:
+      switch(sew) {
+        case VSEW::SEW_E8:
+          return vsetvl_e8m8(avl);
+          break;
+        case VSEW::SEW_E16:
+          return vsetvl_e16m8(avl);
+          break;
+        case VSEW::SEW_E32:
+          return vsetvl_e32m8(avl);
+          break;
+        default:
+          return -1;
+          break;
+      }
+      break;
+    default:
+      break;
+  }
+  return -1;
+}
+
+int get_vsetvlmax_intrinsic(VSEW sew, VLMUL lmul) {
+  switch(lmul) {
+    case VLMUL::LMUL_M1:
+      switch(sew) {
+        case VSEW::SEW_E8:
+          return vsetvlmax_e8m1();
+          break;
+        case VSEW::SEW_E16:
+          return vsetvlmax_e16m1();
+          break;
+        case VSEW::SEW_E32:
+          return vsetvlmax_e32m1();
+          break;
+        default:
+          return -1;
+          break;
+      }
+      break;
+    case VLMUL::LMUL_M2:
+      switch(sew) {
+        case VSEW::SEW_E8:
+          return vsetvlmax_e8m2();
+          break;
+        case VSEW::SEW_E16:
+          return vsetvlmax_e16m2();
+          break;
+        case VSEW::SEW_E32:
+          return vsetvlmax_e32m2();
+          break;
+        default:
+          return -1;
+          break;
+      }
+    case VLMUL::LMUL_M4:
+      switch(sew) {
+        case VSEW::SEW_E8:
+          return vsetvlmax_e8m4();
+          break;
+        case VSEW::SEW_E16:
+          return vsetvlmax_e16m4();
+          break;
+        case VSEW::SEW_E32:
+          return vsetvlmax_e32m4();
+          break;
+        default:
+          return -1;
+          break;
+      }
+      break;
+    case VLMUL::LMUL_M8:
+      switch(sew) {
+        case VSEW::SEW_E8:
+          return vsetvlmax_e8m8();
+          break;
+        case VSEW::SEW_E16:
+          return vsetvlmax_e16m8();
+          break;
+        case VSEW::SEW_E32:
+          return vsetvlmax_e32m8();
+          break;
+        default:
+          return -1;
+          break;
+      }
+      break;
+    default:
+      break;
+  }
+  return -1;
+}
+
+int set_vsetvli(VSEW sew, VLMUL lmul, uint32_t avl) {
+  uint32_t vl = 0;
+  switch(lmul) {
+    case VLMUL::LMUL_M1:
+      switch(sew) {
+          case VSEW::SEW_E8:
+            __asm__ volatile(
+              "vsetvli %[VL], %[AVL], e8, m1"
+              : [VL] "=r" (vl)
+              : [AVL] "r" (avl)
+            );
+            break;
+          case VSEW::SEW_E16:
+            __asm__ volatile(
+              "vsetvli %[VL], %[AVL], e16, m1"
+              : [VL] "=r" (vl)
+              : [AVL] "r" (avl)
+            );
+            break;
+          case VSEW::SEW_E32:
+            __asm__ volatile(
+              "vsetvli %[VL], %[AVL], e32, m1"
+              : [VL] "=r" (vl)
+              : [AVL] "r" (avl)
+            );
+            break;
+          default:
+              return 0;
+      }
+      break;
+    case VLMUL::LMUL_M2:
+      switch(sew) {
+          case VSEW::SEW_E8:
+            __asm__ volatile(
+              "vsetvli %[VL], %[AVL], e8, m2"
+              : [VL] "=r" (vl)
+              : [AVL] "r" (avl)
+            );
+            break;
+          case VSEW::SEW_E16:
+            __asm__ volatile(
+              "vsetvli %[VL], %[AVL], e16, m2"
+              : [VL] "=r" (vl)
+              : [AVL] "r" (avl)
+            );
+            break;
+          case VSEW::SEW_E32:
+            __asm__ volatile(
+              "vsetvli %[VL], %[AVL], e32, m2"
+              : [VL] "=r" (vl)
+              : [AVL] "r" (avl)
+            );
+            break;
+          default:
+              return 0;
+      }
+      break;
+    case VLMUL::LMUL_M4:
+      switch(sew) {
+          case VSEW::SEW_E8:
+            __asm__ volatile(
+              "vsetvli %[VL], %[AVL], e8, m4"
+              : [VL] "=r" (vl)
+              : [AVL] "r" (avl)
+            );
+            break;
+          case VSEW::SEW_E16:
+            __asm__ volatile(
+              "vsetvli %[VL], %[AVL], e16, m4"
+              : [VL] "=r" (vl)
+              : [AVL] "r" (avl)
+            );
+            break;
+          case VSEW::SEW_E32:
+            __asm__ volatile(
+              "vsetvli %[VL], %[AVL], e32, m4"
+              : [VL] "=r" (vl)
+              : [AVL] "r" (avl)
+            );
+            break;
+          default:
+              return 0;
+      }
+      break;
+    case VLMUL::LMUL_M8:
+      switch(sew) {
+          case VSEW::SEW_E8:
+            __asm__ volatile(
+              "vsetvli %[VL], %[AVL], e8, m8"
+              : [VL] "=r" (vl)
+              : [AVL] "r" (avl)
+            );
+            break;
+          case VSEW::SEW_E16:
+            __asm__ volatile(
+              "vsetvli %[VL], %[AVL], e16, m8"
+              : [VL] "=r" (vl)
+              : [AVL] "r" (avl)
+            );
+            break;
+          case VSEW::SEW_E32:
+            __asm__ volatile(
+              "vsetvli %[VL], %[AVL], e32, m8"
+              : [VL] "=r" (vl)
+              : [AVL] "r" (avl)
+            );
+            break;
+          default:
+              return 0;
+      }
+      break;
+    default:
+      return 0;
+  }
+  return vl;
+}
+
+}
diff --git a/tests/vle_vse_test.cpp b/tests/vle_vse_test.cpp
new file mode 100644
index 0000000..80a4172
--- /dev/null
+++ b/tests/vle_vse_test.cpp
@@ -0,0 +1,71 @@
+#include <riscv_vector.h>
+#include <stddef.h>
+#include <springbok_intrinsics.h>
+
+#include "test_v_helpers.h"
+#include "pw_unit_test/framework.h"
+
+namespace vle_vse_test {
+namespace {
+
+using namespace test_v_helpers;
+
+const int VLEN = 512u;
+const int ELEN = 32u;
+const int LMUL_MAX = 8u;
+const int MAXVL_BYTES = VLEN / sizeof(uint8_t) * LMUL_MAX;
+const int AVL_STEP = 4;
+
+uint8_t test_vector_1[MAXVL_BYTES];
+uint8_t test_vector_2[MAXVL_BYTES];
+
+static void vle8vse8_test(VSEW sew, VLMUL lmul, bool use_intrinsic) {
+  int vlmax = get_vsetvlmax_intrinsic(sew, lmul);
+
+  for (int avl = 0; avl <= vlmax; avl+=AVL_STEP) {
+    // clear arrays
+    memset(test_vector_1, 0, MAXVL_BYTES);
+    memset(test_vector_2, 0, MAXVL_BYTES);
+    int vl = set_vsetvl_intrinsic(sew, lmul, avl);
+    EXPECT_EQ(avl, vl);
+    uint8_t *dest = (uint8_t *)test_vector_1;
+    for (int idx = 0; idx < vl; idx++) {
+      dest[idx] = idx;
+    }
+
+    // load c-array values into vector
+    // TODO(gkielian): utilize intrinsics for vle
+    if (use_intrinsic) {
+
+    } else {
+      __asm__ volatile("vle8.v v0, (%0)" : : "r" (test_vector_1));
+
+      // 2) store the vector back into memory (into result c-array)
+      __asm__ volatile("vse8.v v0, (%0)" : : "r" (test_vector_2));
+      }
+    for(int idx = 0; idx < MAXVL_BYTES; idx++)
+    {
+      EXPECT_EQ(test_vector_1[idx], test_vector_2[idx]);
+    }
+  }
+}
+
+TEST(VleVseTest, vle8vse8_e8m1) {
+  vle8vse8_test(VSEW::SEW_E8, VLMUL::LMUL_M1, false);
+}
+
+TEST(VleVseTest, vle8vse8_e8m2) {
+  vle8vse8_test(VSEW::SEW_E8, VLMUL::LMUL_M2, false);
+}
+
+TEST(VleVseTest, vle8vse8_e8m4) {
+  vle8vse8_test(VSEW::SEW_E8, VLMUL::LMUL_M4, false);
+}
+
+TEST(VleVseTest, vle8vse8_e8m8) {
+  vle8vse8_test(VSEW::SEW_E8, VLMUL::LMUL_M8, false);
+}
+
+}  // namespace
+}  // namespace test_vle_vse
+
diff --git a/tests/vsetvl_test.cpp b/tests/vsetvl_test.cpp
new file mode 100644
index 0000000..09dafb4
--- /dev/null
+++ b/tests/vsetvl_test.cpp
@@ -0,0 +1,146 @@
+#include <riscv_vector.h>
+#include <springbok.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "test_v_helpers.h"
+#include "pw_unit_test/framework.h"
+
+namespace vsetvl_test {
+namespace {
+
+using namespace test_v_helpers;
+
+const uint64_t VLEN = 512u;
+const uint64_t ELEN = 32u;
+
+uint32_t AVLS[] = {1,    2,    3,     4,     5,     8,    16,   17,
+                   32,   36,   55,    64,    100,   128,  256,  321,
+                   512,  623,  1024,  1100,  1543,  2048, 3052, 4096,
+                   5555, 8192, 10241, 16384, 24325, 32768};
+const int32_t AVL_COUNT = sizeof(AVLS) / sizeof(AVLS[0]);
+
+#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
+
+static uint32_t calculate_vl(uint32_t sew, uint32_t avl, float lmul) {
+  uint32_t vlmax = (uint32_t)(VLEN * lmul / sew);
+  return MIN(avl, vlmax);
+}
+
+static void test_vsetvl(VSEW sew, VLMUL vlmul, uint32_t width, float lmul) {
+  for (int i = 0; i < AVL_COUNT; i++) {
+    size_t vl = set_vsetvl_intrinsic(sew, vlmul, AVLS[i]);
+    EXPECT_EQ(vl, calculate_vl(width, AVLS[i], lmul));
+  }
+  for (int i = 0; i < AVL_COUNT; i++) {
+    uint32_t vl = set_vsetvl(sew, vlmul, AVLS[i], false, false);
+    EXPECT_EQ(vl, calculate_vl(width, AVLS[i], lmul));
+  }
+  for (int i = 0; i < AVL_COUNT; i++) {
+    uint32_t vl = set_vsetvli(sew, vlmul, AVLS[i]);
+    EXPECT_EQ(vl, calculate_vl(width, AVLS[i], lmul));
+  }
+}
+
+static void test_vsetvlmax(VSEW sew, VLMUL vlmul, uint32_t width, float lmul) {
+  EXPECT_EQ(get_vsetvlmax_intrinsic(sew, vlmul), (int)VLEN / width * lmul);
+}
+
+TEST(VsetvlTest, vsetvl_e8m1) {
+  test_vsetvl(VSEW::SEW_E8, VLMUL::LMUL_M1, 8, 1.0);
+}
+
+TEST(VsetvlTest, vsetvl_e16m1) {
+  test_vsetvl(VSEW::SEW_E16, VLMUL::LMUL_M1, 16, 1.0);
+}
+
+TEST(VsetvlTest, vsetvl_e32m1) {
+  test_vsetvl(VSEW::SEW_E32, VLMUL::LMUL_M1, 32, 1.0);
+}
+
+TEST(VsetvlTest, vsetvl_e8m2) {
+  test_vsetvl(VSEW::SEW_E8, VLMUL::LMUL_M2, 8, 2.0);
+}
+
+TEST(VsetvlTest, vsetvl_e16m2) {
+  test_vsetvl(VSEW::SEW_E16, VLMUL::LMUL_M2, 16, 2.0);
+}
+
+TEST(VsetvlTest, vsetvl_e32m2) {
+  test_vsetvl(VSEW::SEW_E32, VLMUL::LMUL_M2, 32, 2.0);
+}
+
+TEST(VsetvlTest, vsetvl_e8m4) {
+  test_vsetvl(VSEW::SEW_E8, VLMUL::LMUL_M4, 8, 4.0);
+}
+
+TEST(VsetvlTest, vsetvl_e16m4) {
+  test_vsetvl(VSEW::SEW_E16, VLMUL::LMUL_M4, 16, 4.0);
+}
+
+TEST(VsetvlTest, vsetvl_e32m4) {
+    test_vsetvl(VSEW::SEW_E32, VLMUL::LMUL_M4, 32, 4.0);
+}
+
+TEST(VsetvlTest, vsetvl_e8m8) {
+  test_vsetvl(VSEW::SEW_E8, VLMUL::LMUL_M8, 8, 8.0);
+}
+
+TEST(VsetvlTest, vsetvl_e16m8) {
+  test_vsetvl(VSEW::SEW_E16, VLMUL::LMUL_M8, 16, 8);
+}
+
+TEST(VsetvlTest, vsetvl_e32m8) {
+  test_vsetvl(VSEW::SEW_E32, VLMUL::LMUL_M8, 32, 8.0);
+}
+
+TEST(VsetvlTest, vsetvlmax_e8m1) {
+  test_vsetvlmax(VSEW::SEW_E8, VLMUL::LMUL_M1, 8, 1.0);
+}
+
+TEST(VsetvlTest, vsetvlmax_e8m2) {
+  test_vsetvlmax(VSEW::SEW_E8, VLMUL::LMUL_M2, 8, 2.0);
+}
+
+TEST(VsetvlTest, vsetvlmax_e8m4) {
+  test_vsetvlmax(VSEW::SEW_E8, VLMUL::LMUL_M4, 8, 4.0);
+}
+
+TEST(VsetvlTest, vsetvlmax_e8m8) {
+  test_vsetvlmax(VSEW::SEW_E8, VLMUL::LMUL_M8, 8, 8.0);
+}
+
+TEST(VsetvlTest, vsetvlmax_e16m1) {
+  test_vsetvlmax(VSEW::SEW_E16, VLMUL::LMUL_M1, 16, 1.0);
+}
+
+TEST(VsetvlTest, vsetvlmax_e16m2) {
+  test_vsetvlmax(VSEW::SEW_E16, VLMUL::LMUL_M2, 16, 2.0);
+}
+
+TEST(VsetvlTest, vsetvlmax_e16m4) {
+  test_vsetvlmax(VSEW::SEW_E16, VLMUL::LMUL_M4, 16, 4.0);
+}
+
+TEST(VsetvlTest, vsetvlmax_e16m8) {
+  test_vsetvlmax(VSEW::SEW_E16, VLMUL::LMUL_M8, 16, 8.0);
+}
+
+TEST(VsetvlTest, vsetvlmax_e32m1) {
+  test_vsetvlmax(VSEW::SEW_E32, VLMUL::LMUL_M1, 32, 1.0);
+}
+
+TEST(VsetvlTest, vsetvlmax_e32m2) {
+  test_vsetvlmax(VSEW::SEW_E32, VLMUL::LMUL_M2, 32, 2.0);
+}
+
+TEST(VsetvlTest, vsetvlmax_e32m4) {
+  test_vsetvlmax(VSEW::SEW_E32, VLMUL::LMUL_M4, 32, 4.0);
+}
+
+TEST(VsetvlTest, vsetvlmax_e32m8) {
+  test_vsetvlmax(VSEW::SEW_E32, VLMUL::LMUL_M8, 32, 8.0);
+}
+
+}  // namespace
+}  // namespace test_vsetvl
diff --git a/vector_executive/CMakeLists.txt b/vector_executive/CMakeLists.txt
index 1f762cc..4c9d003 100644
--- a/vector_executive/CMakeLists.txt
+++ b/vector_executive/CMakeLists.txt
@@ -1,33 +1,12 @@
-cmake_minimum_required(VERSION 3.10)
 
-project(vector_executive)
-
-set(TARGET vector_executive)
-set(ELF ${TARGET}.elf)
-
-add_executable(${ELF} ${TARGET}.c)
-
-set_target_properties(${ELF} PROPERTIES LINK_DEPENDS "${LINKER_SCRIPT}")
-
-target_link_libraries(${ELF} springbok)
-
-set_target_properties(
-	${ELF}
-	PROPERTIES
-	LINK_FLAGS
-     "-specs=nano.specs \
-    -Wl,--gc-sections \
-    -Wl,--print-memory-usage \
-    -Wl,-Map=${PROJECT_NAME}.map \
-    -T${LINKER_SCRIPT}")
-
-target_compile_options(${ELF} PUBLIC
-    -Wall
-    -Werror
-    -O3
-    -g3
-    -ggdb
-    -ffreestanding
-    -ffunction-sections
-    -fstack-usage
-    -mstrict-align)
+vec_cc_binary(
+    NAME
+      vector_executive
+    SRCS
+      vector_executive.c
+  DEPS
+    springbok
+  LINKOPTS
+    -T${LINKER_SCRIPT}
+    -Xlinker --defsym=__itcm_length__=128K
+)
\ No newline at end of file
diff --git a/vector_load_store_tests/CMakeLists.txt b/vector_load_store_tests/CMakeLists.txt
new file mode 100644
index 0000000..359d042
--- /dev/null
+++ b/vector_load_store_tests/CMakeLists.txt
@@ -0,0 +1,13 @@
+
+vec_cc_binary(
+    NAME
+      vector_load_store_tests
+    SRCS
+      vector_load_store_tests.c
+  DEPS
+    springbok
+    vector_tests
+  LINKOPTS
+    -T${LINKER_SCRIPT}
+    -Xlinker --defsym=__itcm_length__=128K
+)
diff --git a/vector_load_tests/include/vector_load_store_tests.h b/vector_load_store_tests/include/vector_load_store_tests.h
similarity index 100%
rename from vector_load_tests/include/vector_load_store_tests.h
rename to vector_load_store_tests/include/vector_load_store_tests.h
diff --git a/vector_load_tests/vector_load_store_tests.c b/vector_load_store_tests/vector_load_store_tests.c
similarity index 100%
rename from vector_load_tests/vector_load_store_tests.c
rename to vector_load_store_tests/vector_load_store_tests.c
diff --git a/vector_load_tests/CMakeLists.txt b/vector_load_tests/CMakeLists.txt
deleted file mode 100644
index 7d13871..0000000
--- a/vector_load_tests/CMakeLists.txt
+++ /dev/null
@@ -1,35 +0,0 @@
-cmake_minimum_required(VERSION 3.10)
-
-project(vector_load_tests)
-
-
-set(TARGET vector_load_tests)
-set(ELF ${TARGET}.elf)
-
-add_executable(${ELF} vector_load_store_tests.c)
-
-target_include_directories(${ELF} PUBLIC include)
-
-set_target_properties(${ELF} PROPERTIES LINK_DEPENDS "${LINKER_SCRIPT}")
-
-target_link_libraries(${ELF} vector_tests)
-
-set_target_properties(
-	${ELF}
-	PROPERTIES
-	LINK_FLAGS
-	"-T${LINKER_SCRIPT} \
-	 -specs=nano.specs \
-	 -Wl,--gc-sections \
-	 -Wl,--print-memory-usage \
-	 -Wl,-Map=${PROJECT_NAME}.map")
-
-target_compile_options(${ELF} PUBLIC
-	-nostdlib
-	-ffreestanding
-	-ffunction-sections
-	-Wall
-	-Werror
-	-O3
-	-g)
-
diff --git a/vector_tests/CMakeLists.txt b/vector_tests/CMakeLists.txt
index d7f6bc1..e939871 100644
--- a/vector_tests/CMakeLists.txt
+++ b/vector_tests/CMakeLists.txt
@@ -1,4 +1,3 @@
-cmake_minimum_required(VERSION 3.1)
 
 enable_language(ASM)
 add_library(vector_tests
@@ -10,12 +9,5 @@
 target_link_libraries(vector_tests springbok)
 
 target_compile_options(vector_tests PUBLIC
-    -Wall
-    -Werror
-    -O3
-    -g3
-    -ggdb
-    -ffreestanding
-    -ffunction-sections
-    -fstack-usage
-    -mstrict-align)
+      ${VEC_DEFAULT_COPTS}
+)
diff --git a/vector_vadd_vsub_tests/CMakeLists.txt b/vector_vadd_vsub_tests/CMakeLists.txt
index 008773a..dc52f7a 100644
--- a/vector_vadd_vsub_tests/CMakeLists.txt
+++ b/vector_vadd_vsub_tests/CMakeLists.txt
@@ -1,42 +1,20 @@
-cmake_minimum_required(VERSION 3.10)
 
 set (OPERAND_TYPES VV VX VI)
 
 foreach(OPERAND_TYPE ${OPERAND_TYPES})
-project(vector_vadd_vsub_tests_${OPERAND_TYPE})
-
-string(TOLOWER ${OPERAND_TYPE} OP_SUFFIX)
-
-set(TARGET vector_vadd_vsub_tests_${OP_SUFFIX})
-set(ELF ${TARGET}.elf)
-
-add_executable(${ELF} vector_vadd_vsub_tests.c)
-
-target_include_directories(${ELF} PUBLIC include)
-
-set_target_properties(${ELF} PROPERTIES LINK_DEPENDS "${LINKER_SCRIPT}")
-
-target_link_libraries(${ELF} vector_tests)
-
-set_target_properties(
-	${ELF}
-	PROPERTIES
-	LINK_FLAGS
-	"-T${LINKER_SCRIPT} \
-	 -specs=nano.specs \
-	 -Wl,--gc-sections \
-	 -Wl,--print-memory-usage \
-	 -Wl,-Map=${PROJECT_NAME}.map")
-
-target_compile_options(${ELF} PUBLIC
-	-nostdlib
-	-ffreestanding
-	-ffunction-sections
-	-Wall
-	-Werror
-    -Wno-unused-value
-	-O3
-	-g
-    -D=TEST_${OPERAND_TYPE})
-
+vec_cc_binary(
+    NAME
+      vector_vadd_vsub_${OPERAND_TYPE}_tests
+    SRCS
+      vector_vadd_vsub_tests.c
+  DEPS
+    springbok
+    vector_tests
+  COPTS
+   -Wno-unused-value
+   -D=TEST_${OPERAND_TYPE}
+  LINKOPTS
+    -T${LINKER_SCRIPT}
+    -Xlinker --defsym=__itcm_length__=128K
+)
 endforeach()
diff --git a/vector_vset_tests/CMakeLists.txt b/vector_vset_tests/CMakeLists.txt
index ba64c6b..1fa1776 100644
--- a/vector_vset_tests/CMakeLists.txt
+++ b/vector_vset_tests/CMakeLists.txt
@@ -1,35 +1,13 @@
-cmake_minimum_required(VERSION 3.10)
 
-project(vector_vset_tests)
-
-
-set(TARGET vector_vset_tests)
-set(ELF ${TARGET}.elf)
-
-add_executable(${ELF} vector_vset_tests.c)
-
-target_include_directories(${ELF} PUBLIC include)
-
-set_target_properties(${ELF} PROPERTIES LINK_DEPENDS "${LINKER_SCRIPT}")
-
-target_link_libraries(${ELF} vector_tests)
-
-set_target_properties(
-	${ELF}
-	PROPERTIES
-	LINK_FLAGS
-	"-T${LINKER_SCRIPT} \
-	 -specs=nano.specs \
-	 -Wl,--gc-sections \
-	 -Wl,--print-memory-usage \
-	 -Wl,-Map=${PROJECT_NAME}.map")
-
-target_compile_options(${ELF} PUBLIC
-	-nostdlib
-	-ffreestanding
-	-ffunction-sections
-	-Wall
-	-Werror
-	-O3
-	-g)
-
+vec_cc_binary(
+    NAME
+      vector_vset_tests
+    SRCS
+      vector_vset_tests.c
+  DEPS
+    springbok
+    vector_tests
+  LINKOPTS
+    -T${LINKER_SCRIPT}
+    -Xlinker --defsym=__itcm_length__=128K
+)