1 /*
2  * Copyright (C) 2023 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 BERBERIS_INTRINSICS_ALL_TO_X86_32_OR_x86_64_INTRINSICS_BINDINGS_H_
18 #define BERBERIS_INTRINSICS_ALL_TO_X86_32_OR_x86_64_INTRINSICS_BINDINGS_H_
19 
20 #include <xmmintrin.h>
21 
22 #include <cstdint>
23 
24 #include "berberis/base/dependent_false.h"
25 #include "berberis/intrinsics/common/intrinsics_bindings.h"
26 #include "berberis/intrinsics/intrinsics_args.h"
27 #include "berberis/intrinsics/type_traits.h"
28 
29 namespace berberis::intrinsics::bindings {
30 
31 class Imm2 {
32  public:
33   using Type = int8_t;
34   static constexpr bool kIsImmediate = true;
35 };
36 
37 class Imm8 {
38  public:
39   using Type = int8_t;
40   static constexpr bool kIsImmediate = true;
41 };
42 
43 class Imm16 {
44  public:
45   using Type = int16_t;
46   static constexpr bool kIsImmediate = true;
47 };
48 
49 class Imm32 {
50  public:
51   using Type = int32_t;
52   static constexpr bool kIsImmediate = true;
53 };
54 
55 class Imm64 {
56  public:
57   using Type = int64_t;
58   static constexpr bool kIsImmediate = true;
59 };
60 
61 class AL {
62  public:
63   using Type = uint8_t;
64   static constexpr bool kIsImmediate = false;
65   static constexpr bool kIsImplicitReg = true;
66   static constexpr char kAsRegister = 'a';
67   template <typename MachineInsnArch>
68   static constexpr auto kRegClass = MachineInsnArch::kAL;
69 };
70 
71 class AX {
72  public:
73   using Type = uint16_t;
74   static constexpr bool kIsImmediate = false;
75   static constexpr bool kIsImplicitReg = true;
76   static constexpr char kAsRegister = 'a';
77 };
78 
79 class EAX {
80  public:
81   using Type = uint32_t;
82   static constexpr bool kIsImmediate = false;
83   static constexpr bool kIsImplicitReg = true;
84   static constexpr char kAsRegister = 'a';
85   template <typename MachineInsnArch>
86   static constexpr auto kRegClass = MachineInsnArch::kEAX;
87 };
88 
89 class RAX {
90  public:
91   using Type = uint32_t;
92   static constexpr bool kIsImmediate = false;
93   static constexpr bool kIsImplicitReg = true;
94   static constexpr char kAsRegister = 'a';
95   template <typename MachineInsnArch>
96   static constexpr auto kRegClass = MachineInsnArch::kRAX;
97 };
98 
99 class CL {
100  public:
101   using Type = uint8_t;
102   static constexpr bool kIsImmediate = false;
103   static constexpr bool kIsImplicitReg = true;
104   static constexpr char kAsRegister = 'c';
105   template <typename MachineInsnArch>
106   static constexpr auto kRegClass = MachineInsnArch::kCL;
107 };
108 
109 class CX {
110  public:
111   using Type = uint16_t;
112   static constexpr bool kIsImmediate = false;
113   static constexpr bool kIsImplicitReg = true;
114   static constexpr char kAsRegister = 'c';
115 };
116 
117 class ECX {
118  public:
119   using Type = uint32_t;
120   static constexpr bool kIsImmediate = false;
121   static constexpr bool kIsImplicitReg = true;
122   static constexpr char kAsRegister = 'c';
123   template <typename MachineInsnArch>
124   static constexpr auto kRegClass = MachineInsnArch::kECX;
125 };
126 
127 class RCX {
128  public:
129   using Type = uint32_t;
130   static constexpr bool kIsImmediate = false;
131   static constexpr bool kIsImplicitReg = true;
132   static constexpr char kAsRegister = 'c';
133   template <typename MachineInsnArch>
134   static constexpr auto kRegClass = MachineInsnArch::kRCX;
135 };
136 
137 class DL {
138  public:
139   using Type = uint8_t;
140   static constexpr bool kIsImmediate = false;
141   static constexpr bool kIsImplicitReg = true;
142   static constexpr char kAsRegister = 'd';
143 };
144 
145 class DX {
146  public:
147   using Type = uint16_t;
148   static constexpr bool kIsImmediate = false;
149   static constexpr bool kIsImplicitReg = true;
150   static constexpr char kAsRegister = 'd';
151 };
152 
153 class EDX {
154  public:
155   using Type = uint32_t;
156   static constexpr bool kIsImmediate = false;
157   static constexpr bool kIsImplicitReg = true;
158   static constexpr char kAsRegister = 'd';
159   template <typename MachineInsnArch>
160   static constexpr auto kRegClass = MachineInsnArch::kEDX;
161 };
162 
163 class RDX {
164  public:
165   using Type = uint32_t;
166   static constexpr bool kIsImmediate = false;
167   static constexpr bool kIsImplicitReg = true;
168   static constexpr char kAsRegister = 'd';
169   template <typename MachineInsnArch>
170   static constexpr auto kRegClass = MachineInsnArch::kRDX;
171 };
172 
173 class GeneralReg8 {
174  public:
175   using Type = uint8_t;
176   static constexpr bool kIsImmediate = false;
177   static constexpr bool kIsImplicitReg = false;
178   static constexpr char kAsRegister = 'q';
179   template <typename MachineInsnArch>
180   static constexpr auto kRegClass = MachineInsnArch::kGeneralReg8;
181 };
182 
183 class GeneralReg16 {
184  public:
185   using Type = uint16_t;
186   static constexpr bool kIsImmediate = false;
187   static constexpr bool kIsImplicitReg = false;
188   static constexpr char kAsRegister = 'r';
189   template <typename MachineInsnArch>
190   static constexpr auto kRegClass = MachineInsnArch::kGeneralReg16;
191 };
192 
193 class GeneralReg32 {
194  public:
195   using Type = uint32_t;
196   static constexpr bool kIsImmediate = false;
197   static constexpr bool kIsImplicitReg = false;
198   static constexpr char kAsRegister = 'r';
199   template <typename MachineInsnArch>
200   static constexpr auto kRegClass = MachineInsnArch::kGeneralReg32;
201 };
202 
203 class GeneralReg64 {
204  public:
205   using Type = uint64_t;
206   static constexpr bool kIsImmediate = false;
207   static constexpr bool kIsImplicitReg = false;
208   static constexpr char kAsRegister = 'r';
209   template <typename MachineInsnArch>
210   static constexpr auto kRegClass = MachineInsnArch::kGeneralReg64;
211 };
212 
213 class FpReg32 {
214  public:
215   using Type = __m128;
216   static constexpr bool kIsImmediate = false;
217   static constexpr bool kIsImplicitReg = false;
218   static constexpr char kAsRegister = 'x';
219   template <typename MachineInsnArch>
220   static constexpr auto kRegClass = MachineInsnArch::kFpReg32;
221 };
222 
223 class FpReg64 {
224  public:
225   using Type = __m128;
226   static constexpr bool kIsImmediate = false;
227   static constexpr bool kIsImplicitReg = false;
228   static constexpr char kAsRegister = 'x';
229   template <typename MachineInsnArch>
230   static constexpr auto kRegClass = MachineInsnArch::kFpReg64;
231 };
232 
233 class VecReg128 {
234  public:
235   using Type = __m128;
236   static constexpr bool kIsImmediate = false;
237   static constexpr bool kIsImplicitReg = false;
238   static constexpr char kAsRegister = 'x';
239   template <typename MachineInsnArch>
240   static constexpr auto kRegClass = MachineInsnArch::kVecReg128;
241 };
242 
243 class XmmReg {
244  public:
245   using Type = __m128;
246   static constexpr bool kIsImmediate = false;
247   static constexpr bool kIsImplicitReg = false;
248   static constexpr char kAsRegister = 'x';
249   template <typename MachineInsnArch>
250   static constexpr auto kRegClass = MachineInsnArch::kXmmReg;
251 };
252 
253 class MemX87 {
254  public:
255   static constexpr bool kIsImmediate = false;
256   static constexpr char kAsRegister = 'm';
257 };
258 
259 // Tag classes. They are never instantioned, only used as tags to pass information about
260 // bindings.
261 class NoCPUIDRestriction;
262 class Has3DNOW;
263 class Has3DNOWP;
264 class HasADX;
265 class HasAES;
266 class HasAESAVX;
267 class HasAMXBF16;
268 class HasAMXFP16;
269 class HasAMXINT8;
270 class HasAMXTILE;
271 class HasAVX;
272 class HasAVX2;
273 class HasAVX5124FMAPS;
274 class HasAVX5124VNNIW;
275 class HasAVX512BF16;
276 class HasAVX512BITALG;
277 class HasAVX512BW;
278 class HasAVX512CD;
279 class HasAVX512DQ;
280 class HasAVX512ER;
281 class HasAVX512F;
282 class HasAVX512FP16;
283 class HasAVX512IFMA;
284 class HasAVX512PF;
285 class HasAVX512VBMI;
286 class HasAVX512VBMI2;
287 class HasAVX512VL;
288 class HasAVX512VNNI;
289 class HasAVX512VPOPCNTDQ;
290 class HasBMI;
291 class HasBMI2;
292 class HasCLMUL;
293 class HasCMOV;
294 class HasCMPXCHG16B;
295 class HasCMPXCHG8B;
296 class HasF16C;
297 class HasFMA;
298 class HasFMA4;
299 class HasFXSAVE;
300 class HasLZCNT;
301 // BMI2 is set and PDEP/PEXT are ok to use. See more here:
302 //   https://twitter.com/instlatx64/status/1322503571288559617
303 class HashPDEP;
304 class HasPOPCNT;
305 class HasRDSEED;
306 class HasSERIALIZE;
307 class HasSHA;
308 class HasSSE;
309 class HasSSE2;
310 class HasSSE3;
311 class HasSSE4_1;
312 class HasSSE4_2;
313 class HasSSE4a;
314 class HasSSSE3;
315 class HasTBM;
316 class HasVAES;
317 class HasX87;
318 class HasCustomCapability;
319 class IsAuthenticAMD;
320 
321 }  // namespace berberis::intrinsics::bindings
322 
323 #endif  // BERBERIS_INTRINSICS_ALL_TO_X86_32_OR_x86_64_INTRINSICS_BINDINGS_H_
324