1 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 Copyright (c) 2008-2017, Petr Kobalicek
3
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
7
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
11
12 1. The origin of this software must not be misrepresented; you must not
13 claim that you wrote the original software. If you use this software
14 in a product, an acknowledgment in the product documentation would be
15 appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17 misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
19 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
20 #ifdef __PLUMED_HAS_ASMJIT
21 #pragma GCC diagnostic push
22 #pragma GCC diagnostic ignored "-Wpedantic"
23 // [AsmJit]
24 // Complete x86/x64 JIT and Remote Assembler for C++.
25 //
26 // [License]
27 // Zlib - See LICENSE.md file in the package.
28
29 // [Export]
30 #define ASMJIT_EXPORTS
31
32 // [Dependencies]
33 #include "./operand.h"
34
35 // [Api-Begin]
36 #include "./asmjit_apibegin.h"
37
38 namespace PLMD {
39 namespace asmjit {
40
41 // ============================================================================
42 // [asmjit::TypeId]
43 // ============================================================================
44
45 template<int ID>
46 struct TypeIdSizeOf_T {
47 enum {
48 kValue = (ID == TypeId::kI8 ) ? 1 :
49 (ID == TypeId::kU8 ) ? 1 :
50 (ID == TypeId::kI16 ) ? 2 :
51 (ID == TypeId::kU16 ) ? 2 :
52 (ID == TypeId::kI32 ) ? 4 :
53 (ID == TypeId::kU32 ) ? 4 :
54 (ID == TypeId::kI64 ) ? 8 :
55 (ID == TypeId::kU64 ) ? 8 :
56 (ID == TypeId::kF32 ) ? 4 :
57 (ID == TypeId::kF64 ) ? 8 :
58 (ID == TypeId::kF80 ) ? 10 :
59 (ID == TypeId::kMask8 ) ? 1 :
60 (ID == TypeId::kMask16) ? 2 :
61 (ID == TypeId::kMask32) ? 4 :
62 (ID == TypeId::kMask64) ? 8 :
63 (ID == TypeId::kMmx32 ) ? 4 :
64 (ID == TypeId::kMmx64 ) ? 8 :
65 (ID >= TypeId::_kVec32Start && ID <= TypeId::_kVec32End ) ? 4 :
66 (ID >= TypeId::_kVec64Start && ID <= TypeId::_kVec64End ) ? 8 :
67 (ID >= TypeId::_kVec128Start && ID <= TypeId::_kVec128End) ? 16 :
68 (ID >= TypeId::_kVec256Start && ID <= TypeId::_kVec256End) ? 32 :
69 (ID >= TypeId::_kVec512Start && ID <= TypeId::_kVec512End) ? 64 : 0
70 };
71 };
72
73 template<int ID>
74 struct TypeIdElementOf_T {
75 enum {
76 kValue = (ID == TypeId::kMask8 ) ? TypeId::kU8 :
77 (ID == TypeId::kMask16) ? TypeId::kU16 :
78 (ID == TypeId::kMask32) ? TypeId::kU32 :
79 (ID == TypeId::kMask64) ? TypeId::kU64 :
80 (ID == TypeId::kMmx32 ) ? TypeId::kI32 :
81 (ID == TypeId::kMmx64 ) ? TypeId::kI64 :
82 (ID >= TypeId::kI8 && ID <= TypeId::kF80 ) ? ID :
83 (ID >= TypeId::_kVec32Start && ID <= TypeId::_kVec32End ) ? ID - TypeId::_kVec32Start + TypeId::kI8 :
84 (ID >= TypeId::_kVec64Start && ID <= TypeId::_kVec64End ) ? ID - TypeId::_kVec64Start + TypeId::kI8 :
85 (ID >= TypeId::_kVec128Start && ID <= TypeId::_kVec128End) ? ID - TypeId::_kVec128Start + TypeId::kI8 :
86 (ID >= TypeId::_kVec256Start && ID <= TypeId::_kVec256End) ? ID - TypeId::_kVec256Start + TypeId::kI8 :
87 (ID >= TypeId::_kVec512Start && ID <= TypeId::_kVec512End) ? ID - TypeId::_kVec512Start + TypeId::kI8 : 0
88 };
89 };
90
91 #define R(TMPL, I) TMPL<I + 0>::kValue, TMPL<I + 1>::kValue, \
92 TMPL<I + 2>::kValue, TMPL<I + 3>::kValue, \
93 TMPL<I + 4>::kValue, TMPL<I + 5>::kValue, \
94 TMPL<I + 6>::kValue, TMPL<I + 7>::kValue, \
95 TMPL<I + 8>::kValue, TMPL<I + 9>::kValue, \
96 TMPL<I + 10>::kValue, TMPL<I + 11>::kValue, \
97 TMPL<I + 12>::kValue, TMPL<I + 13>::kValue, \
98 TMPL<I + 14>::kValue, TMPL<I + 15>::kValue
99 ASMJIT_API const TypeId::Info TypeId::_info = {
100 // SizeOf[128]
101 {
102 R(TypeIdSizeOf_T, 0), R(TypeIdSizeOf_T, 16),
103 R(TypeIdSizeOf_T, 32), R(TypeIdSizeOf_T, 48),
104 R(TypeIdSizeOf_T, 64), R(TypeIdSizeOf_T, 80),
105 R(TypeIdSizeOf_T, 96), R(TypeIdSizeOf_T, 112)
106 },
107
108 // ElementOf[128]
109 {
110 R(TypeIdElementOf_T, 0), R(TypeIdElementOf_T, 16),
111 R(TypeIdElementOf_T, 32), R(TypeIdElementOf_T, 48),
112 R(TypeIdElementOf_T, 64), R(TypeIdElementOf_T, 80),
113 R(TypeIdElementOf_T, 96), R(TypeIdElementOf_T, 112)
114 }
115 };
116 #undef R
117
118 // ============================================================================
119 // [asmjit::Operand - Test]
120 // ============================================================================
121
122 #if defined(ASMJIT_TEST)
UNIT(base_operand)123 UNIT(base_operand) {
124 INFO("Checking operand sizes");
125 EXPECT(sizeof(Operand) == 16);
126 EXPECT(sizeof(Reg) == 16);
127 EXPECT(sizeof(Mem) == 16);
128 EXPECT(sizeof(Imm) == 16);
129 EXPECT(sizeof(Label) == 16);
130
131 INFO("Checking basic functionality of Operand");
132 Operand a, b;
133 Operand dummy;
134
135 EXPECT(a.isNone() == true);
136 EXPECT(a.isReg() == false);
137 EXPECT(a.isMem() == false);
138 EXPECT(a.isImm() == false);
139 EXPECT(a.isLabel() == false);
140 EXPECT(a == b);
141
142 EXPECT(a._any.reserved8_4 == 0, "Default constructed Operand should zero its 'reserved8_4' field");
143 EXPECT(a._any.reserved12_4 == 0, "Default constructed Operand should zero its 'reserved12_4' field");
144
145 INFO("Checking basic functionality of Label");
146 Label label;
147 EXPECT(label.isValid() == false);
148 EXPECT(label.getId() == 0);
149
150 INFO("Checking basic functionality of Reg");
151 EXPECT(Reg().isValid() == false,
152 "Default constructed Reg() should not be valid");
153 EXPECT(Reg()._any.reserved8_4 == 0,
154 "A default constructed Reg() should zero its 'reserved8_4' field");
155 EXPECT(Reg()._any.reserved12_4 == 0,
156 "A default constructed Reg() should zero its 'reserved12_4' field");
157
158 EXPECT(Reg().isReg() == false,
159 "Default constructed register should not isReg()");
160 EXPECT(dummy.as<Reg>().isValid() == false,
161 "Default constructed Operand casted to Reg should not be valid");
162
163 // Create some register (not specific to any architecture).
164 uint32_t rSig = Operand::kOpReg | (1 << Operand::kSignatureRegTypeShift) |
165 (2 << Operand::kSignatureRegKindShift) |
166 (8 << Operand::kSignatureSizeShift ) ;
167 Reg r1(Reg::fromSignature(rSig, 5));
168
169 EXPECT(r1.isValid() == true);
170 EXPECT(r1.isReg() == true);
171 EXPECT(r1.isReg(1) == true);
172 EXPECT(r1.isPhysReg() == true);
173 EXPECT(r1.isVirtReg() == false);
174 EXPECT(r1.getSignature() == rSig);
175 EXPECT(r1.getType() == 1);
176 EXPECT(r1.getKind() == 2);
177 EXPECT(r1.getSize() == 8);
178 EXPECT(r1.getId() == 5);
179 EXPECT(r1.isReg(1, 5) == true); // RegType and Id.
180
181 EXPECT(r1._any.reserved8_4 == 0, "Reg should have 'reserved8_4' zero");
182 EXPECT(r1._any.reserved12_4 == 0, "Reg should have 'reserved12_4' zero");
183
184 // The same type of register having different id.
185 Reg r2(r1, 6);
186 EXPECT(r2.isValid() == true);
187 EXPECT(r2.isReg() == true);
188 EXPECT(r2.isReg(1) == true);
189 EXPECT(r2.isPhysReg() == true);
190 EXPECT(r2.isVirtReg() == false);
191 EXPECT(r2.getSignature() == rSig);
192 EXPECT(r2.getType() == r1.getType());
193 EXPECT(r2.getKind() == r1.getKind());
194 EXPECT(r2.getSize() == r1.getSize());
195 EXPECT(r2.getId() == 6);
196 EXPECT(r2.isReg(1, 6) == true);
197
198 r1.reset();
199 EXPECT(!r1.isValid(),
200 "Reset register should not be valid");
201 EXPECT(!r1.isReg(),
202 "Reset register should not isReg()");
203
204 INFO("Checking basic functionality of Mem");
205 Mem m;
206 EXPECT(m.isMem() , "Default constructed Mem() should isMem()");
207 EXPECT(m == Mem() , "Two default constructed Mem() operands should be equal");
208 EXPECT(m.hasBase() == false , "Default constructed Mem() should not have base specified");
209 EXPECT(m.hasIndex() == false , "Default constructed Mem() should not have index specified");
210 EXPECT(m.has64BitOffset() == true , "Default constructed Mem() should report 64-bit offset");
211 EXPECT(m.getOffset() == 0 , "Default constructed Mem() should have be zero offset / address");
212
213 m.setOffset(-1);
214 EXPECT(m.getOffsetLo32() == -1 , "Memory operand must hold a 32-bit offset");
215 EXPECT(m.getOffset() == -1 , "32-bit offset must be sign extended to 64 bits");
216
217 int64_t x = int64_t(ASMJIT_UINT64_C(0xFF00FF0000000001));
218 m.setOffset(x);
219 EXPECT(m.getOffset() == x , "Memory operand must hold a 64-bit offset");
220 EXPECT(m.getOffsetLo32() == 1 , "Memory operand must return correct low offset DWORD");
221 EXPECT(m.getOffsetHi32() == 0xFF00FF00, "Memory operand must return correct high offset DWORD");
222
223 INFO("Checking basic functionality of Imm");
224 EXPECT(Imm(-1).getInt64() == int64_t(-1),
225 "Immediate values should by default sign-extend to 64-bits");
226 }
227 #endif // ASMJIT_TEST
228
229 } // asmjit namespace
230 } // namespace PLMD
231
232 // [Api-End]
233 #include "./asmjit_apiend.h"
234 #pragma GCC diagnostic pop
235 #endif // __PLUMED_HAS_ASMJIT
236