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