1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef RISCV64_TO_X86_64_BERBERIS_INTRINSICS_MACRO_ASSEMBLER_CONSTANTS_POOL_H_
18 #define RISCV64_TO_X86_64_BERBERIS_INTRINSICS_MACRO_ASSEMBLER_CONSTANTS_POOL_H_
19 
20 #include <cinttypes>
21 
22 #include "berberis/base/dependent_false.h"
23 #include "berberis/intrinsics/common/intrinsics_float.h"
24 
25 namespace berberis::constants_pool {
26 
27 // Vector constants, that is: constants are repeated to fill 128bit SIMD register.
28 template <auto Value>
29 inline constexpr int32_t kVectorConst = kImpossibleValueConst<Value>;
30 template <>
31 extern const int32_t kVectorConst<int8_t{-128}>;
32 template <>
33 extern const int32_t kVectorConst<int8_t{127}>;
34 template <>
35 extern const int32_t kVectorConst<int16_t{-0x8000}>;
36 template <>
37 extern const int32_t kVectorConst<int16_t{0x7fff}>;
38 template <>
39 extern const int32_t kVectorConst<int32_t{static_cast<int32_t>(-0x8000'0000)}>;
40 template <>
41 extern const int32_t kVectorConst<int32_t{-0x0080'0000}>;
42 template <>
43 extern const int32_t kVectorConst<int32_t{0x3f80'0000}>;
44 template <>
45 extern const int32_t kVectorConst<int32_t{0x7f80'0000}>;
46 template <>
47 extern const int32_t kVectorConst<int32_t{0x7fff'ffff}>;
48 template <>
49 extern const int32_t kVectorConst<int64_t{static_cast<int64_t>(-0x8000'0000'0000'0000)}>;
50 template <>
51 extern const int32_t kVectorConst<int64_t{0x3ff0'0000'0000'0000}>;
52 template <>
53 extern const int32_t kVectorConst<int64_t{0x7ff0'0000'0000'0000}>;
54 template <>
55 extern const int32_t kVectorConst<int64_t{0x7fff'ffff'ffff'ffff}>;
56 template <>
57 extern const int32_t kVectorConst<int64_t{-0x0010'0000'0000'0000}>;
58 template <>
59 extern const int32_t kVectorConst<uint64_t{0x0000'0000'0000'0000}>;
60 template <>
61 inline const int32_t& kVectorConst<int8_t{0x00}> = kVectorConst<uint64_t{0x0000'0000'0000'0000}>;
62 template <>
63 inline const int32_t& kVectorConst<uint8_t{0x00}> = kVectorConst<uint64_t{0x0000'0000'0000'0000}>;
64 template <>
65 inline const int32_t& kVectorConst<int16_t{0x0000}> = kVectorConst<uint64_t{0x0000'0000'0000'0000}>;
66 template <>
67 inline const int32_t& kVectorConst<uint16_t{0x0000}> =
68     kVectorConst<uint64_t{0x0000'0000'0000'0000}>;
69 template <>
70 inline const int32_t& kVectorConst<uint8_t{127}> = kVectorConst<int8_t{127}>;
71 template <>
72 inline const int32_t& kVectorConst<uint8_t{128}> = kVectorConst<int8_t{-128}>;
73 template <>
74 inline const int32_t& kVectorConst<uint16_t{0x7fff}> = kVectorConst<int16_t{0x7fff}>;
75 template <>
76 inline const int32_t& kVectorConst<uint16_t{0x8000}> = kVectorConst<int16_t{-0x8000}>;
77 template <>
78 inline const int32_t& kVectorConst<int32_t{0x0000'0000}> =
79     kVectorConst<uint64_t{0x0000'0000'0000'0000}>;
80 template <>
81 inline const int32_t& kVectorConst<uint32_t{0x0000'0000}> =
82     kVectorConst<uint64_t{0x0000'0000'0000'0000}>;
83 template <>
84 inline const int32_t& kVectorConst<uint32_t{0x3f80'0000}> = kVectorConst<int32_t{0x3f80'0000}>;
85 template <>
86 inline const int32_t& kVectorConst<uint32_t{0x7f80'0000}> = kVectorConst<int32_t{0x7f80'0000}>;
87 template <>
88 inline const int32_t& kVectorConst<uint32_t{0x7fff'ffff}> = kVectorConst<int32_t{0x7fff'ffff}>;
89 template <>
90 inline const int32_t& kVectorConst<uint32_t{0x8000'0000}> =
91     kVectorConst<int32_t{static_cast<int32_t>(-0x8000'0000)}>;
92 template <>
93 inline const int32_t& kVectorConst<uint32_t{0xff80'0000}> = kVectorConst<int32_t{-0x0080'0000}>;
94 template <>
95 inline const int32_t& kVectorConst<int64_t{0x0000'0000'0000'0000}> =
96     kVectorConst<uint64_t{0x0000'0000'0000'0000}>;
97 template <>
98 extern const int32_t kVectorConst<uint64_t{0x7fc'00000'7fc'00000}>;
99 template <>
100 inline const int32_t& kVectorConst<uint64_t{0x7ff0'0000'0000'0000}> =
101     kVectorConst<int64_t{0x7ff0'0000'0000'0000}>;
102 template <>
103 extern const int32_t kVectorConst<uint64_t{0x7ff8'0000'0000'0000}>;
104 template <>
105 inline const int32_t& kVectorConst<uint64_t{0xfff0'0000'0000'0000}> =
106     kVectorConst<int64_t{-0x0010'0000'0000'0000}>;
107 template <>
108 extern const int32_t kVectorConst<uint64_t{0xffff'ffff'0000'0000}>;
109 template <>
110 extern const int32_t kVectorConst<uint64_t{0xffff'ffff'7fc0'0000}>;
111 template <>
112 extern const int32_t kVectorConst<uint64_t{0xffff'ffff'ffff'ffff}>;
113 template <>
114 inline const int32_t& kVectorConst<int8_t{-1}> = kVectorConst<uint64_t{0xffff'ffff'ffff'ffff}>;
115 template <>
116 inline const int32_t& kVectorConst<uint8_t{0xff}> = kVectorConst<uint64_t{0xffff'ffff'ffff'ffff}>;
117 template <>
118 inline const int32_t& kVectorConst<int16_t{-1}> = kVectorConst<uint64_t{0xffff'ffff'ffff'ffff}>;
119 template <>
120 inline const int32_t& kVectorConst<uint16_t{0xffff}> =
121     kVectorConst<uint64_t{0xffff'ffff'ffff'ffff}>;
122 template <>
123 inline const int32_t& kVectorConst<int32_t{-1}> = kVectorConst<uint64_t{0xffff'ffff'ffff'ffff}>;
124 template <>
125 inline const int32_t& kVectorConst<uint32_t{0xffff'ffff}> =
126     kVectorConst<uint64_t{0xffff'ffff'ffff'ffff}>;
127 template <>
128 inline const int32_t& kVectorConst<int64_t{-1}> = kVectorConst<uint64_t{0xffff'ffff'ffff'ffff}>;
129 
130 // 64 bit constants for use with arithmetic operations.
131 // Used because only 32 bit immediates are supported on x86-64.
132 template <auto Value>
133 inline constexpr int32_t kConst = kImpossibleValueConst<Value>;
134 template <>
135 extern const int32_t kConst<uint32_t{32}>;
136 template <>
137 extern const int32_t kConst<uint32_t{63}>;
138 template <>
139 extern const int32_t kConst<uint64_t{64}>;
140 template <>
141 extern const int32_t kConst<uint64_t{127}>;
142 template <>
143 extern const int32_t kVectorConst<uint64_t{0x0000'0000'0000'0000}>;
144 template <>
145 inline const int32_t& kConst<int8_t{0x00}> = kVectorConst<uint64_t{0x0000'0000'0000'0000}>;
146 template <>
147 inline const int32_t& kConst<uint8_t{0x00}> = kVectorConst<uint64_t{0x0000'0000'0000'0000}>;
148 template <>
149 inline const int32_t& kConst<int16_t{0x0000}> = kVectorConst<uint64_t{0x0000'0000'0000'0000}>;
150 template <>
151 inline const int32_t& kConst<uint16_t{0x0000}> = kVectorConst<uint64_t{0x0000'0000'0000'0000}>;
152 template <>
153 inline const int32_t& kConst<int32_t{0x0000'0000}> = kVectorConst<uint64_t{0x0000'0000'0000'0000}>;
154 template <>
155 inline const int32_t& kConst<uint32_t{0x0000'0000}> = kVectorConst<uint64_t{0x0000'0000'0000'0000}>;
156 template <>
157 inline const int32_t& kConst<int64_t{0x0000'0000'0000'0000}> =
158     kVectorConst<uint64_t{0x0000'0000'0000'0000}>;
159 template <>
160 inline const int32_t& kConst<uint64_t{0x0000'0000'0000'0000}> =
161     kVectorConst<uint64_t{0x0000'0000'0000'0000}>;
162 template <>
163 extern const int32_t kConst<uint64_t{0x8000'0000'0000'00ff}>;
164 template <>
165 extern const int32_t kVectorConst<uint64_t{0xffff'ffff'ffff'ffff}>;
166 template <>
167 inline const int32_t& kConst<int8_t{-1}> = kVectorConst<uint64_t{0xffff'ffff'ffff'ffff}>;
168 template <>
169 inline const int32_t& kConst<uint8_t{0xff}> = kVectorConst<uint64_t{0xffff'ffff'ffff'ffff}>;
170 template <>
171 inline const int32_t& kConst<int16_t{-1}> = kVectorConst<uint64_t{0xffff'ffff'ffff'ffff}>;
172 template <>
173 inline const int32_t& kConst<uint16_t{0xffff}> = kVectorConst<uint64_t{0xffff'ffff'ffff'ffff}>;
174 template <>
175 inline const int32_t& kConst<int32_t{-1}> = kVectorConst<uint64_t{0xffff'ffff'ffff'ffff}>;
176 template <>
177 inline const int32_t& kConst<uint32_t{0xffff'ffff}> = kVectorConst<uint64_t{0xffff'ffff'ffff'ffff}>;
178 template <>
179 inline const int32_t& kConst<int64_t{-1}> = kVectorConst<uint64_t{0xffff'ffff'ffff'ffff}>;
180 template <>
181 inline const int32_t& kConst<uint64_t{0xffff'ffff'ffff'ffff}> =
182     kVectorConst<uint64_t{0xffff'ffff'ffff'ffff}>;
183 
184 // Constant suitable for NaN boxing of RISC-V 32bit float with PXor.
185 // Note: technically we only need to Nan-box Float32 since we don't support Float16 yet.
186 template <typename FloatType>
187 inline constexpr int32_t kNanBox = kImpossibleTypeConst<FloatType>;
188 template <>
189 inline const int32_t& kNanBox<intrinsics::Float32> = kVectorConst<uint64_t{0xffff'ffff'0000'0000}>;
190 
191 // Canonically Nan boxed canonical NaN.
192 // Note: technically we only need to Nan-box Float32 since we don't support Float16 yet.
193 template <typename FloatType>
194 inline constexpr int32_t kNanBoxedNans = kImpossibleTypeConst<FloatType>;
195 template <>
196 inline const int32_t& kNanBoxedNans<intrinsics::Float32> =
197     kVectorConst<uint64_t{0xffff'ffff'7fc0'0000}>;
198 
199 // Canonical NaNs. Float32 and Float64 are supported.
200 template <typename FloatType>
201 inline constexpr int32_t kCanonicalNans = kImpossibleTypeConst<FloatType>;
202 template <>
203 inline const int32_t& kCanonicalNans<intrinsics::Float32> =
204     kVectorConst<uint64_t{0x7fc0'0000'7fc0'0000}>;
205 template <>
206 inline const int32_t& kCanonicalNans<intrinsics::Float64> =
207     kVectorConst<uint64_t{0x7ff8'0000'0000'0000}>;
208 
209 // Helper constant for BsrToClz conversion. 63 for int32_t, 127 for int64_t.
210 template <typename IntType>
211 inline constexpr int32_t kBsrToClz = kImpossibleTypeConst<IntType>;
212 template <>
213 inline const int32_t kBsrToClz<int32_t> = kConst<uint32_t{63}>;
214 template <>
215 inline const int32_t kBsrToClz<int64_t> = kConst<uint64_t{127}>;
216 
217 // Helper constant for width of the type. 32 for int32_t, 64 for int64_t.
218 template <typename IntType>
219 inline constexpr int32_t kWidthInBits = kImpossibleTypeConst<IntType>;
220 template <>
221 inline const int32_t kWidthInBits<int32_t> = kConst<uint32_t{32}>;
222 template <>
223 inline const int32_t kWidthInBits<int64_t> = kConst<uint64_t{64}>;
224 
225 extern const int32_t kRiscVToX87Exceptions;
226 extern const int32_t kX87ToRiscVExceptions;
227 
228 extern const int32_t kVid64Bit;
229 extern const int32_t kVid32Bit;
230 extern const int32_t kVid16Bit;
231 extern const int32_t kVid8Bit;
232 
233 extern const int32_t kBitMaskTable;
234 extern const int32_t kBitMaskTo32bitMask;
235 extern const int32_t kBitMaskTo16bitMask;
236 extern const int32_t kBitMaskTo8bitMask;
237 
238 extern const int32_t kPMovmskwToPMovmskb;
239 extern const int32_t kPMovmskdToPMovmskb;
240 extern const int32_t kPMovmskqToPMovmskb;
241 
242 }  // namespace berberis::constants_pool
243 
244 #endif  // RISCV64_TO_X86_64_BERBERIS_INTRINSICS_MACRO_ASSEMBLER_CONSTANTS_POOL_H_
245