Line data Source code
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 : #ifndef __PLUMED_asmjit_x86compiler_h
21 : #define __PLUMED_asmjit_x86compiler_h
22 : #ifdef __PLUMED_HAS_ASMJIT
23 : #pragma GCC diagnostic push
24 : #pragma GCC diagnostic ignored "-Wpedantic"
25 : // [AsmJit]
26 : // Complete x86/x64 JIT and Remote Assembler for C++.
27 : //
28 : // [License]
29 : // Zlib - See LICENSE.md file in the package.
30 :
31 : // [Guard]
32 : #ifndef _ASMJIT_X86_X86COMPILER_H
33 : #define _ASMJIT_X86_X86COMPILER_H
34 :
35 : #include "./asmjit_build.h"
36 : #if !defined(ASMJIT_DISABLE_COMPILER)
37 :
38 : // [Dependencies]
39 : #include "./codecompiler.h"
40 : #include "./simdtypes.h"
41 : #include "./x86emitter.h"
42 : #include "./x86misc.h"
43 :
44 : // [Api-Begin]
45 : #include "./asmjit_apibegin.h"
46 :
47 : namespace PLMD {
48 : namespace asmjit {
49 :
50 : //! \addtogroup asmjit_x86
51 : //! \{
52 :
53 : // ============================================================================
54 : // [asmjit::X86Compiler]
55 : // ============================================================================
56 :
57 : //! Architecture-dependent \ref CodeCompiler targeting X86 and X64.
58 : class ASMJIT_VIRTAPI X86Compiler
59 : : public CodeCompiler,
60 : public X86EmitterExplicitT<X86Compiler> {
61 :
62 : public:
63 : ASMJIT_NONCOPYABLE(X86Compiler)
64 : typedef CodeCompiler Base;
65 :
66 : // --------------------------------------------------------------------------
67 : // [Construction / Destruction]
68 : // --------------------------------------------------------------------------
69 :
70 : //! Create a `X86Compiler` instance.
71 : ASMJIT_API X86Compiler(CodeHolder* code = nullptr) noexcept;
72 : //! Destroy the `X86Compiler` instance.
73 : ASMJIT_API ~X86Compiler() noexcept;
74 :
75 : // --------------------------------------------------------------------------
76 : // [Compatibility]
77 : // --------------------------------------------------------------------------
78 :
79 : //! Explicit cast to `X86Emitter`.
80 : ASMJIT_INLINE X86Emitter* asEmitter() noexcept { return reinterpret_cast<X86Emitter*>(this); }
81 : //! Explicit cast to `X86Emitter` (const).
82 : ASMJIT_INLINE const X86Emitter* asEmitter() const noexcept { return reinterpret_cast<const X86Emitter*>(this); }
83 :
84 : //! Implicit cast to `X86Emitter`.
85 : ASMJIT_INLINE operator X86Emitter&() noexcept { return *asEmitter(); }
86 : //! Implicit cast to `X86Emitter` (const).
87 : ASMJIT_INLINE operator const X86Emitter&() const noexcept { return *asEmitter(); }
88 :
89 : // --------------------------------------------------------------------------
90 : // [Events]
91 : // --------------------------------------------------------------------------
92 :
93 : ASMJIT_API virtual Error onAttach(CodeHolder* code) noexcept override;
94 :
95 : // --------------------------------------------------------------------------
96 : // [Code-Generation]
97 : // --------------------------------------------------------------------------
98 :
99 : ASMJIT_API virtual Error _emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) override;
100 : ASMJIT_API virtual Error _emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4, const Operand_& o5) override;
101 :
102 : // -------------------------------------------------------------------------
103 : // [Finalize]
104 : // -------------------------------------------------------------------------
105 :
106 : ASMJIT_API virtual Error finalize() override;
107 :
108 : // --------------------------------------------------------------------------
109 : // [VirtReg]
110 : // --------------------------------------------------------------------------
111 :
112 : #if !defined(ASMJIT_DISABLE_LOGGING)
113 : #define ASMJIT_NEW_REG(OUT, PARAM, NAME_FMT) \
114 : va_list ap; \
115 : va_start(ap, NAME_FMT); \
116 : _newReg(OUT, PARAM, NAME_FMT, ap); \
117 : va_end(ap)
118 : #else
119 : #define ASMJIT_NEW_REG(OUT, PARAM, NAME_FMT) \
120 : ASMJIT_UNUSED(NAME_FMT); \
121 : _newReg(OUT, PARAM, nullptr)
122 : #endif
123 :
124 : #define ASMJIT_NEW_REG_USER(FUNC, REG) \
125 : ASMJIT_INLINE REG FUNC(uint32_t typeId) { \
126 : REG reg(NoInit); \
127 : _newReg(reg, typeId, nullptr); \
128 : return reg; \
129 : } \
130 : \
131 : REG FUNC(uint32_t typeId, const char* nameFmt, ...) { \
132 : REG reg(NoInit); \
133 : ASMJIT_NEW_REG(reg, typeId, nameFmt); \
134 : return reg; \
135 : }
136 :
137 : #define ASMJIT_NEW_REG_AUTO(FUNC, REG, TYPE_ID) \
138 : ASMJIT_INLINE REG FUNC() { \
139 : REG reg(NoInit); \
140 : _newReg(reg, TYPE_ID, nullptr); \
141 : return reg; \
142 : } \
143 : \
144 : REG FUNC(const char* nameFmt, ...) { \
145 : REG reg(NoInit); \
146 : ASMJIT_NEW_REG(reg, TYPE_ID, nameFmt); \
147 : return reg; \
148 : }
149 :
150 : template<typename RegT>
151 : ASMJIT_INLINE RegT newSimilarReg(const RegT& ref) {
152 : RegT reg(NoInit);
153 : _newReg(reg, ref, nullptr);
154 : return reg;
155 : }
156 :
157 : template<typename RegT>
158 : RegT newSimilarReg(const RegT& ref, const char* nameFmt, ...) {
159 : RegT reg(NoInit);
160 : ASMJIT_NEW_REG(reg, ref, nameFmt);
161 : return reg;
162 : }
163 :
164 0 : ASMJIT_NEW_REG_USER(newReg , X86Reg )
165 : ASMJIT_NEW_REG_USER(newGpReg , X86Gp )
166 : ASMJIT_NEW_REG_USER(newMmReg , X86Mm )
167 : ASMJIT_NEW_REG_USER(newKReg , X86KReg)
168 : ASMJIT_NEW_REG_USER(newXmmReg , X86Xmm )
169 : ASMJIT_NEW_REG_USER(newYmmReg , X86Ymm )
170 : ASMJIT_NEW_REG_USER(newZmmReg , X86Zmm )
171 :
172 : ASMJIT_NEW_REG_AUTO(newI8 , X86Gp , TypeId::kI8 )
173 : ASMJIT_NEW_REG_AUTO(newU8 , X86Gp , TypeId::kU8 )
174 : ASMJIT_NEW_REG_AUTO(newI16 , X86Gp , TypeId::kI16 )
175 : ASMJIT_NEW_REG_AUTO(newU16 , X86Gp , TypeId::kU16 )
176 : ASMJIT_NEW_REG_AUTO(newI32 , X86Gp , TypeId::kI32 )
177 : ASMJIT_NEW_REG_AUTO(newU32 , X86Gp , TypeId::kU32 )
178 : ASMJIT_NEW_REG_AUTO(newI64 , X86Gp , TypeId::kI64 )
179 : ASMJIT_NEW_REG_AUTO(newU64 , X86Gp , TypeId::kU64 )
180 : ASMJIT_NEW_REG_AUTO(newInt8 , X86Gp , TypeId::kI8 )
181 : ASMJIT_NEW_REG_AUTO(newUInt8 , X86Gp , TypeId::kU8 )
182 : ASMJIT_NEW_REG_AUTO(newInt16 , X86Gp , TypeId::kI16 )
183 : ASMJIT_NEW_REG_AUTO(newUInt16 , X86Gp , TypeId::kU16 )
184 : ASMJIT_NEW_REG_AUTO(newInt32 , X86Gp , TypeId::kI32 )
185 : ASMJIT_NEW_REG_AUTO(newUInt32 , X86Gp , TypeId::kU32 )
186 : ASMJIT_NEW_REG_AUTO(newInt64 , X86Gp , TypeId::kI64 )
187 : ASMJIT_NEW_REG_AUTO(newUInt64 , X86Gp , TypeId::kU64 )
188 7248 : ASMJIT_NEW_REG_AUTO(newIntPtr , X86Gp , TypeId::kIntPtr )
189 : ASMJIT_NEW_REG_AUTO(newUIntPtr, X86Gp , TypeId::kUIntPtr)
190 :
191 : ASMJIT_NEW_REG_AUTO(newGpb , X86Gp , TypeId::kU8 )
192 : ASMJIT_NEW_REG_AUTO(newGpw , X86Gp , TypeId::kU16 )
193 : ASMJIT_NEW_REG_AUTO(newGpd , X86Gp , TypeId::kU32 )
194 : ASMJIT_NEW_REG_AUTO(newGpq , X86Gp , TypeId::kU64 )
195 0 : ASMJIT_NEW_REG_AUTO(newGpz , X86Gp , TypeId::kUIntPtr)
196 : ASMJIT_NEW_REG_AUTO(newKb , X86KReg, TypeId::kMask8 )
197 : ASMJIT_NEW_REG_AUTO(newKw , X86KReg, TypeId::kMask16 )
198 : ASMJIT_NEW_REG_AUTO(newKd , X86KReg, TypeId::kMask32 )
199 : ASMJIT_NEW_REG_AUTO(newKq , X86KReg, TypeId::kMask64 )
200 : ASMJIT_NEW_REG_AUTO(newMm , X86Mm , TypeId::kMmx64 )
201 : ASMJIT_NEW_REG_AUTO(newXmm , X86Xmm , TypeId::kI32x4 )
202 : ASMJIT_NEW_REG_AUTO(newXmmSs , X86Xmm , TypeId::kF32x1 )
203 16492 : ASMJIT_NEW_REG_AUTO(newXmmSd , X86Xmm , TypeId::kF64x1 )
204 : ASMJIT_NEW_REG_AUTO(newXmmPs , X86Xmm , TypeId::kF32x4 )
205 : ASMJIT_NEW_REG_AUTO(newXmmPd , X86Xmm , TypeId::kF64x2 )
206 : ASMJIT_NEW_REG_AUTO(newYmm , X86Ymm , TypeId::kI32x8 )
207 : ASMJIT_NEW_REG_AUTO(newYmmPs , X86Ymm , TypeId::kF32x8 )
208 : ASMJIT_NEW_REG_AUTO(newYmmPd , X86Ymm , TypeId::kF64x4 )
209 : ASMJIT_NEW_REG_AUTO(newZmm , X86Zmm , TypeId::kI32x16 )
210 : ASMJIT_NEW_REG_AUTO(newZmmPs , X86Zmm , TypeId::kF32x16 )
211 : ASMJIT_NEW_REG_AUTO(newZmmPd , X86Zmm , TypeId::kF64x8 )
212 :
213 : #undef ASMJIT_NEW_REG_AUTO
214 : #undef ASMJIT_NEW_REG_USER
215 : #undef ASMJIT_NEW_REG
216 :
217 : // --------------------------------------------------------------------------
218 : // [Stack]
219 : // --------------------------------------------------------------------------
220 :
221 : //! Create a new memory chunk allocated on the current function's stack.
222 : ASMJIT_INLINE X86Mem newStack(uint32_t size, uint32_t alignment, const char* name = nullptr) {
223 : X86Mem m(NoInit);
224 : _newStack(m, size, alignment, name);
225 : return m;
226 : }
227 :
228 : // --------------------------------------------------------------------------
229 : // [Const]
230 : // --------------------------------------------------------------------------
231 :
232 : //! Put data to a constant-pool and get a memory reference to it.
233 : ASMJIT_INLINE X86Mem newConst(uint32_t scope, const void* data, size_t size) {
234 : X86Mem m(NoInit);
235 : _newConst(m, scope, data, size);
236 : return m;
237 : }
238 :
239 : //! Put a BYTE `val` to a constant-pool.
240 : ASMJIT_INLINE X86Mem newByteConst(uint32_t scope, uint8_t val) noexcept { return newConst(scope, &val, 1); }
241 : //! Put a WORD `val` to a constant-pool.
242 : ASMJIT_INLINE X86Mem newWordConst(uint32_t scope, uint16_t val) noexcept { return newConst(scope, &val, 2); }
243 : //! Put a DWORD `val` to a constant-pool.
244 : ASMJIT_INLINE X86Mem newDWordConst(uint32_t scope, uint32_t val) noexcept { return newConst(scope, &val, 4); }
245 : //! Put a QWORD `val` to a constant-pool.
246 : ASMJIT_INLINE X86Mem newQWordConst(uint32_t scope, uint64_t val) noexcept { return newConst(scope, &val, 8); }
247 :
248 : //! Put a WORD `val` to a constant-pool.
249 : ASMJIT_INLINE X86Mem newInt16Const(uint32_t scope, int16_t val) noexcept { return newConst(scope, &val, 2); }
250 : //! Put a WORD `val` to a constant-pool.
251 : ASMJIT_INLINE X86Mem newUInt16Const(uint32_t scope, uint16_t val) noexcept { return newConst(scope, &val, 2); }
252 : //! Put a DWORD `val` to a constant-pool.
253 : ASMJIT_INLINE X86Mem newInt32Const(uint32_t scope, int32_t val) noexcept { return newConst(scope, &val, 4); }
254 : //! Put a DWORD `val` to a constant-pool.
255 : ASMJIT_INLINE X86Mem newUInt32Const(uint32_t scope, uint32_t val) noexcept { return newConst(scope, &val, 4); }
256 : //! Put a QWORD `val` to a constant-pool.
257 : ASMJIT_INLINE X86Mem newInt64Const(uint32_t scope, int64_t val) noexcept { return newConst(scope, &val, 8); }
258 : //! Put a QWORD `val` to a constant-pool.
259 : ASMJIT_INLINE X86Mem newUInt64Const(uint32_t scope, uint64_t val) noexcept { return newConst(scope, &val, 8); }
260 :
261 : //! Put a SP-FP `val` to a constant-pool.
262 : ASMJIT_INLINE X86Mem newFloatConst(uint32_t scope, float val) noexcept { return newConst(scope, &val, 4); }
263 : //! Put a DP-FP `val` to a constant-pool.
264 : ASMJIT_INLINE X86Mem newDoubleConst(uint32_t scope, double val) noexcept { return newConst(scope, &val, 8); }
265 :
266 : //! Put a MMX `val` to a constant-pool.
267 : ASMJIT_INLINE X86Mem newMmConst(uint32_t scope, const Data64& val) noexcept { return newConst(scope, &val, 8); }
268 : //! Put a XMM `val` to a constant-pool.
269 : ASMJIT_INLINE X86Mem newXmmConst(uint32_t scope, const Data128& val) noexcept { return newConst(scope, &val, 16); }
270 : //! Put a YMM `val` to a constant-pool.
271 : ASMJIT_INLINE X86Mem newYmmConst(uint32_t scope, const Data256& val) noexcept { return newConst(scope, &val, 32); }
272 :
273 : // -------------------------------------------------------------------------
274 : // [Instruction Options]
275 : // -------------------------------------------------------------------------
276 :
277 : //! Force the compiler to not follow the conditional or unconditional jump.
278 : ASMJIT_INLINE X86Compiler& unfollow() noexcept { _options |= kOptionUnfollow; return *this; }
279 : //! Tell the compiler that the destination variable will be overwritten.
280 : ASMJIT_INLINE X86Compiler& overwrite() noexcept { _options |= kOptionOverwrite; return *this; }
281 :
282 : // --------------------------------------------------------------------------
283 : // [Emit]
284 : // --------------------------------------------------------------------------
285 :
286 : //! Call a function.
287 1636 : ASMJIT_INLINE CCFuncCall* call(const X86Gp& dst, const FuncSignature& sign) { return addCall(X86Inst::kIdCall, dst, sign); }
288 : //! \overload
289 : ASMJIT_INLINE CCFuncCall* call(const X86Mem& dst, const FuncSignature& sign) { return addCall(X86Inst::kIdCall, dst, sign); }
290 : //! \overload
291 : ASMJIT_INLINE CCFuncCall* call(const Label& label, const FuncSignature& sign) { return addCall(X86Inst::kIdCall, label, sign); }
292 : //! \overload
293 : ASMJIT_INLINE CCFuncCall* call(const Imm& dst, const FuncSignature& sign) { return addCall(X86Inst::kIdCall, dst, sign); }
294 : //! \overload
295 : ASMJIT_INLINE CCFuncCall* call(uint64_t dst, const FuncSignature& sign) { return addCall(X86Inst::kIdCall, Imm(dst), sign); }
296 :
297 : //! Return.
298 : ASMJIT_INLINE CCFuncRet* ret() { return addRet(Operand(), Operand()); }
299 : //! \overload
300 : ASMJIT_INLINE CCFuncRet* ret(const X86Gp& o0) { return addRet(o0, Operand()); }
301 : //! \overload
302 : ASMJIT_INLINE CCFuncRet* ret(const X86Gp& o0, const X86Gp& o1) { return addRet(o0, o1); }
303 : //! \overload
304 1944 : ASMJIT_INLINE CCFuncRet* ret(const X86Xmm& o0) { return addRet(o0, Operand()); }
305 : //! \overload
306 : ASMJIT_INLINE CCFuncRet* ret(const X86Xmm& o0, const X86Xmm& o1) { return addRet(o0, o1); }
307 : };
308 :
309 : //! \}
310 :
311 : } // asmjit namespace
312 : } // namespace PLMD
313 :
314 : // [Api-End]
315 : #include "./asmjit_apiend.h"
316 :
317 : // [Guard]
318 : #endif // !ASMJIT_DISABLE_COMPILER
319 : #endif // _ASMJIT_X86_X86COMPILER_H
320 : #pragma GCC diagnostic pop
321 : #endif // __PLUMED_HAS_ASMJIT
322 : #endif
|