add setvl
[simplev-cpp.git] / include / simplev_cpp.h
1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 // See Notices.txt for copyright information
3 #pragma once
4
5 #ifndef __cplusplus
6 #error to use SimpleV Cpp with C, include "simplev_c.h"
7 #endif
8
9 #include <cstddef>
10 #include <cstdint>
11 #include <type_traits>
12
13 template <typename ElementType, std::size_t MAX_VL, typename = void>
14 struct SVVecTypeStruct;
15
16 template <typename ElementType, std::size_t MAX_VL>
17 using SVVecType = typename SVVecTypeStruct<ElementType, MAX_VL>::Type;
18
19
20 #define MAKE_VEC_TYPE(size) \
21 template <typename ElementType, std::size_t MAX_VL> \
22 struct SVVecTypeStruct<ElementType, \
23 MAX_VL, \
24 std::enable_if_t<sizeof(ElementType) * MAX_VL == (size)>> \
25 final \
26 { \
27 typedef ElementType Type __attribute__((vector_size(size))); \
28 };
29
30 MAKE_VEC_TYPE(1)
31 MAKE_VEC_TYPE(2)
32 MAKE_VEC_TYPE(3)
33 MAKE_VEC_TYPE(4)
34 MAKE_VEC_TYPE(5)
35 MAKE_VEC_TYPE(6)
36 MAKE_VEC_TYPE(7)
37 MAKE_VEC_TYPE(8)
38
39 #undef MAKE_VEC_TYPE
40
41 template <typename ElementType, std::size_t MAX_VL>
42 struct SVVec final
43 {
44 using Type = SVVecType<ElementType, MAX_VL>;
45 Type value;
46 };
47
48 struct Mask final
49 {
50 std::uint64_t value = ~0ULL;
51 };
52
53 template <size_t MAX_VL = 64>
54 struct VL final
55 {
56 std::size_t value = MAX_VL;
57 };
58
59 namespace opcodes
60 {
61 inline constexpr std::size_t PRIMARY_OPCODE_SHIFT = 32 - 6;
62 /// unofficial value. see https://libre-soc.org/openpower/sv/setvl/
63 /// FIXME: incorrect extended opcode value
64 inline constexpr std::uint32_t SETVL_OPCODE = (19 << PRIMARY_OPCODE_SHIFT) | (0 << 1);
65 inline constexpr std::size_t SETVL_IMMEDIATE_SHIFT = 32 - 7 - 16;
66 inline constexpr std::size_t REG_FIELD_WIDTH = 5;
67 inline constexpr std::size_t XL_FORM_RT_SHIFT = 32 - REG_FIELD_WIDTH - 6;
68 inline constexpr std::size_t XL_FORM_RA_SHIFT = 32 - REG_FIELD_WIDTH - 11;
69 } // namespace opcodes
70
71 #define SETVL_ASM(retval, vl) \
72 "# setvl " retval ", " vl \
73 ", MVL=%[max_vl]\n\t" \
74 ".long %[setvl_opcode] | (" retval " << %[xl_form_rt_shift]) | (" vl \
75 " << %[xl_form_ra_shift]) | ((%[max_vl] - 1) << %[setvl_immediate_shift])"
76
77 #define SETVL_ASM_INPUT_ARGS() \
78 [setvl_opcode] "n"(opcodes::SETVL_OPCODE), \
79 [setvl_immediate_shift] "n"(opcodes::SETVL_IMMEDIATE_SHIFT), \
80 [xl_form_rt_shift] "n"(opcodes::XL_FORM_RT_SHIFT), \
81 [xl_form_ra_shift] "n"(opcodes::XL_FORM_RA_SHIFT)
82
83 template <std::size_t MAX_VL>
84 inline __attribute__((always_inline)) VL<MAX_VL> sv_setvl(std::size_t vl)
85 {
86 static_assert(MAX_VL > 0 && MAX_VL < 64);
87 VL<MAX_VL> retval;
88 asm(SETVL_ASM("%[retval]", "%[vl]")
89 : [retval] "=b"(retval.value)
90 : [vl] "b"(vl), [max_vl] "n"(MAX_VL), SETVL_ASM_INPUT_ARGS());
91 return retval;
92 }