x86compiler.h 13 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.

// [Guard]
#ifndef _ASMJIT_X86_X86COMPILER_H
#define _ASMJIT_X86_X86COMPILER_H

11
#include "../asmjit_build.h"
12
13
#if !defined(ASMJIT_DISABLE_COMPILER)

14
15
16
17
18
// [Dependencies]
#include "../base/codecompiler.h"
#include "../base/simdtypes.h"
#include "../x86/x86emitter.h"
#include "../x86/x86misc.h"
19
20

// [Api-Begin]
21
#include "../asmjit_apibegin.h"
22
23
24

namespace asmjit {

25
//! \addtogroup asmjit_x86
26
27
28
//! \{

// ============================================================================
29
// [asmjit::X86Compiler]
30
31
// ============================================================================

32
33
34
35
//! Architecture-dependent \ref CodeCompiler targeting X86 and X64.
class ASMJIT_VIRTAPI X86Compiler
  : public CodeCompiler,
    public X86EmitterExplicitT<X86Compiler> {
36

37
38
39
public:
  ASMJIT_NONCOPYABLE(X86Compiler)
  typedef CodeCompiler Base;
40
41

  // --------------------------------------------------------------------------
42
  // [Construction / Destruction]
43
44
  // --------------------------------------------------------------------------

45
46
47
48
  //! Create a `X86Compiler` instance.
  ASMJIT_API X86Compiler(CodeHolder* code = nullptr) noexcept;
  //! Destroy the `X86Compiler` instance.
  ASMJIT_API ~X86Compiler() noexcept;
49
50

  // --------------------------------------------------------------------------
51
  // [Compatibility]
52
53
  // --------------------------------------------------------------------------

54
55
56
57
  //! Explicit cast to `X86Emitter`.
  ASMJIT_INLINE X86Emitter* asEmitter() noexcept { return reinterpret_cast<X86Emitter*>(this); }
  //! Explicit cast to `X86Emitter` (const).
  ASMJIT_INLINE const X86Emitter* asEmitter() const noexcept { return reinterpret_cast<const X86Emitter*>(this); }
58

59
60
61
62
  //! Implicit cast to `X86Emitter`.
  ASMJIT_INLINE operator X86Emitter&() noexcept { return *asEmitter(); }
  //! Implicit cast to `X86Emitter` (const).
  ASMJIT_INLINE operator const X86Emitter&() const noexcept { return *asEmitter(); }
63
64

  // --------------------------------------------------------------------------
65
  // [Events]
66
67
  // --------------------------------------------------------------------------

68
  ASMJIT_API virtual Error onAttach(CodeHolder* code) noexcept override;
69
70

  // --------------------------------------------------------------------------
71
  // [Code-Generation]
72
73
  // --------------------------------------------------------------------------

74
75
  ASMJIT_API virtual Error _emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) override;
  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;
76

77
78
79
  // -------------------------------------------------------------------------
  // [Finalize]
  // -------------------------------------------------------------------------
80

81
  ASMJIT_API virtual Error finalize() override;
82
83

  // --------------------------------------------------------------------------
84
  // [VirtReg]
85
86
  // --------------------------------------------------------------------------

87
88
89
90
91
92
93
94
95
96
97
#if !defined(ASMJIT_DISABLE_LOGGING)
#define ASMJIT_NEW_REG(OUT, PARAM, NAME_FMT)            \
  va_list ap;                                           \
  va_start(ap, NAME_FMT);                               \
  _newReg(OUT, PARAM, NAME_FMT, ap);                    \
  va_end(ap)
#else
#define ASMJIT_NEW_REG(OUT, PARAM, NAME_FMT)            \
  ASMJIT_UNUSED(NAME_FMT);                              \
  _newReg(OUT, PARAM, nullptr)
#endif
98

99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#define ASMJIT_NEW_REG_USER(FUNC, REG)                  \
  ASMJIT_INLINE REG FUNC(uint32_t typeId) {             \
    REG reg(NoInit);                                    \
    _newReg(reg, typeId, nullptr);                      \
    return reg;                                         \
  }                                                     \
                                                        \
  REG FUNC(uint32_t typeId, const char* nameFmt, ...) { \
    REG reg(NoInit);                                    \
    ASMJIT_NEW_REG(reg, typeId, nameFmt);               \
    return reg;                                         \
  }

#define ASMJIT_NEW_REG_AUTO(FUNC, REG, TYPE_ID)         \
  ASMJIT_INLINE REG FUNC() {                            \
    REG reg(NoInit);                                    \
    _newReg(reg, TYPE_ID, nullptr);                     \
    return reg;                                         \
  }                                                     \
                                                        \
  REG FUNC(const char* nameFmt, ...) {                  \
    REG reg(NoInit);                                    \
    ASMJIT_NEW_REG(reg, TYPE_ID, nameFmt);              \
    return reg;                                         \
  }

  template<typename RegT>
  ASMJIT_INLINE RegT newSimilarReg(const RegT& ref) {
    RegT reg(NoInit);
    _newReg(reg, ref, nullptr);
    return reg;
  }

  template<typename RegT>
  RegT newSimilarReg(const RegT& ref, const char* nameFmt, ...) {
    RegT reg(NoInit);
    ASMJIT_NEW_REG(reg, ref, nameFmt);
    return reg;
  }

  ASMJIT_NEW_REG_USER(newReg    , X86Reg )
  ASMJIT_NEW_REG_USER(newGpReg  , X86Gp  )
  ASMJIT_NEW_REG_USER(newMmReg  , X86Mm  )
  ASMJIT_NEW_REG_USER(newKReg   , X86KReg)
  ASMJIT_NEW_REG_USER(newXmmReg , X86Xmm )
  ASMJIT_NEW_REG_USER(newYmmReg , X86Ymm )
  ASMJIT_NEW_REG_USER(newZmmReg , X86Zmm )

  ASMJIT_NEW_REG_AUTO(newI8     , X86Gp  , TypeId::kI8     )
  ASMJIT_NEW_REG_AUTO(newU8     , X86Gp  , TypeId::kU8     )
  ASMJIT_NEW_REG_AUTO(newI16    , X86Gp  , TypeId::kI16    )
  ASMJIT_NEW_REG_AUTO(newU16    , X86Gp  , TypeId::kU16    )
  ASMJIT_NEW_REG_AUTO(newI32    , X86Gp  , TypeId::kI32    )
  ASMJIT_NEW_REG_AUTO(newU32    , X86Gp  , TypeId::kU32    )
  ASMJIT_NEW_REG_AUTO(newI64    , X86Gp  , TypeId::kI64    )
  ASMJIT_NEW_REG_AUTO(newU64    , X86Gp  , TypeId::kU64    )
  ASMJIT_NEW_REG_AUTO(newInt8   , X86Gp  , TypeId::kI8     )
  ASMJIT_NEW_REG_AUTO(newUInt8  , X86Gp  , TypeId::kU8     )
  ASMJIT_NEW_REG_AUTO(newInt16  , X86Gp  , TypeId::kI16    )
  ASMJIT_NEW_REG_AUTO(newUInt16 , X86Gp  , TypeId::kU16    )
  ASMJIT_NEW_REG_AUTO(newInt32  , X86Gp  , TypeId::kI32    )
  ASMJIT_NEW_REG_AUTO(newUInt32 , X86Gp  , TypeId::kU32    )
  ASMJIT_NEW_REG_AUTO(newInt64  , X86Gp  , TypeId::kI64    )
  ASMJIT_NEW_REG_AUTO(newUInt64 , X86Gp  , TypeId::kU64    )
  ASMJIT_NEW_REG_AUTO(newIntPtr , X86Gp  , TypeId::kIntPtr )
  ASMJIT_NEW_REG_AUTO(newUIntPtr, X86Gp  , TypeId::kUIntPtr)

  ASMJIT_NEW_REG_AUTO(newGpb    , X86Gp  , TypeId::kU8     )
  ASMJIT_NEW_REG_AUTO(newGpw    , X86Gp  , TypeId::kU16    )
  ASMJIT_NEW_REG_AUTO(newGpd    , X86Gp  , TypeId::kU32    )
  ASMJIT_NEW_REG_AUTO(newGpq    , X86Gp  , TypeId::kU64    )
  ASMJIT_NEW_REG_AUTO(newGpz    , X86Gp  , TypeId::kUIntPtr)
  ASMJIT_NEW_REG_AUTO(newKb     , X86KReg, TypeId::kMask8  )
  ASMJIT_NEW_REG_AUTO(newKw     , X86KReg, TypeId::kMask16 )
  ASMJIT_NEW_REG_AUTO(newKd     , X86KReg, TypeId::kMask32 )
  ASMJIT_NEW_REG_AUTO(newKq     , X86KReg, TypeId::kMask64 )
  ASMJIT_NEW_REG_AUTO(newMm     , X86Mm  , TypeId::kMmx64  )
  ASMJIT_NEW_REG_AUTO(newXmm    , X86Xmm , TypeId::kI32x4  )
  ASMJIT_NEW_REG_AUTO(newXmmSs  , X86Xmm , TypeId::kF32x1  )
  ASMJIT_NEW_REG_AUTO(newXmmSd  , X86Xmm , TypeId::kF64x1  )
  ASMJIT_NEW_REG_AUTO(newXmmPs  , X86Xmm , TypeId::kF32x4  )
  ASMJIT_NEW_REG_AUTO(newXmmPd  , X86Xmm , TypeId::kF64x2  )
  ASMJIT_NEW_REG_AUTO(newYmm    , X86Ymm , TypeId::kI32x8  )
  ASMJIT_NEW_REG_AUTO(newYmmPs  , X86Ymm , TypeId::kF32x8  )
  ASMJIT_NEW_REG_AUTO(newYmmPd  , X86Ymm , TypeId::kF64x4  )
  ASMJIT_NEW_REG_AUTO(newZmm    , X86Zmm , TypeId::kI32x16 )
  ASMJIT_NEW_REG_AUTO(newZmmPs  , X86Zmm , TypeId::kF32x16 )
  ASMJIT_NEW_REG_AUTO(newZmmPd  , X86Zmm , TypeId::kF64x8  )

#undef ASMJIT_NEW_REG_AUTO
#undef ASMJIT_NEW_REG_USER
#undef ASMJIT_NEW_REG
191
192

  // --------------------------------------------------------------------------
193
  // [Stack]
194
195
  // --------------------------------------------------------------------------

196
197
198
199
200
  //! Create a new memory chunk allocated on the current function's stack.
  ASMJIT_INLINE X86Mem newStack(uint32_t size, uint32_t alignment, const char* name = nullptr) {
    X86Mem m(NoInit);
    _newStack(m, size, alignment, name);
    return m;
201
202
203
  }

  // --------------------------------------------------------------------------
204
  // [Const]
205
206
  // --------------------------------------------------------------------------

207
208
209
210
211
212
  //! Put data to a constant-pool and get a memory reference to it.
  ASMJIT_INLINE X86Mem newConst(uint32_t scope, const void* data, size_t size) {
    X86Mem m(NoInit);
    _newConst(m, scope, data, size);
    return m;
  }
213

214
215
216
217
218
219
220
221
  //! Put a BYTE `val` to a constant-pool.
  ASMJIT_INLINE X86Mem newByteConst(uint32_t scope, uint8_t val) noexcept { return newConst(scope, &val, 1); }
  //! Put a WORD `val` to a constant-pool.
  ASMJIT_INLINE X86Mem newWordConst(uint32_t scope, uint16_t val) noexcept { return newConst(scope, &val, 2); }
  //! Put a DWORD `val` to a constant-pool.
  ASMJIT_INLINE X86Mem newDWordConst(uint32_t scope, uint32_t val) noexcept { return newConst(scope, &val, 4); }
  //! Put a QWORD `val` to a constant-pool.
  ASMJIT_INLINE X86Mem newQWordConst(uint32_t scope, uint64_t val) noexcept { return newConst(scope, &val, 8); }
222

223
224
225
226
227
228
229
230
231
232
233
234
  //! Put a WORD `val` to a constant-pool.
  ASMJIT_INLINE X86Mem newInt16Const(uint32_t scope, int16_t val) noexcept { return newConst(scope, &val, 2); }
  //! Put a WORD `val` to a constant-pool.
  ASMJIT_INLINE X86Mem newUInt16Const(uint32_t scope, uint16_t val) noexcept { return newConst(scope, &val, 2); }
  //! Put a DWORD `val` to a constant-pool.
  ASMJIT_INLINE X86Mem newInt32Const(uint32_t scope, int32_t val) noexcept { return newConst(scope, &val, 4); }
  //! Put a DWORD `val` to a constant-pool.
  ASMJIT_INLINE X86Mem newUInt32Const(uint32_t scope, uint32_t val) noexcept { return newConst(scope, &val, 4); }
  //! Put a QWORD `val` to a constant-pool.
  ASMJIT_INLINE X86Mem newInt64Const(uint32_t scope, int64_t val) noexcept { return newConst(scope, &val, 8); }
  //! Put a QWORD `val` to a constant-pool.
  ASMJIT_INLINE X86Mem newUInt64Const(uint32_t scope, uint64_t val) noexcept { return newConst(scope, &val, 8); }
235

236
237
238
239
  //! Put a SP-FP `val` to a constant-pool.
  ASMJIT_INLINE X86Mem newFloatConst(uint32_t scope, float val) noexcept { return newConst(scope, &val, 4); }
  //! Put a DP-FP `val` to a constant-pool.
  ASMJIT_INLINE X86Mem newDoubleConst(uint32_t scope, double val) noexcept { return newConst(scope, &val, 8); }
240

241
242
243
244
245
246
  //! Put a MMX `val` to a constant-pool.
  ASMJIT_INLINE X86Mem newMmConst(uint32_t scope, const Data64& val) noexcept { return newConst(scope, &val, 8); }
  //! Put a XMM `val` to a constant-pool.
  ASMJIT_INLINE X86Mem newXmmConst(uint32_t scope, const Data128& val) noexcept { return newConst(scope, &val, 16); }
  //! Put a YMM `val` to a constant-pool.
  ASMJIT_INLINE X86Mem newYmmConst(uint32_t scope, const Data256& val) noexcept { return newConst(scope, &val, 32); }
247

248
249
250
  // -------------------------------------------------------------------------
  // [Instruction Options]
  // -------------------------------------------------------------------------
251

252
253
254
255
  //! Force the compiler to not follow the conditional or unconditional jump.
  ASMJIT_INLINE X86Compiler& unfollow() noexcept { _options |= kOptionUnfollow; return *this; }
  //! Tell the compiler that the destination variable will be overwritten.
  ASMJIT_INLINE X86Compiler& overwrite() noexcept { _options |= kOptionOverwrite; return *this; }
256

257
258
259
  // --------------------------------------------------------------------------
  // [Emit]
  // --------------------------------------------------------------------------
260

261
262
  //! Call a function.
  ASMJIT_INLINE CCFuncCall* call(const X86Gp& dst, const FuncSignature& sign) { return addCall(X86Inst::kIdCall, dst, sign); }
263
  //! \overload
264
  ASMJIT_INLINE CCFuncCall* call(const X86Mem& dst, const FuncSignature& sign) { return addCall(X86Inst::kIdCall, dst, sign); }
265
  //! \overload
266
  ASMJIT_INLINE CCFuncCall* call(const Label& label, const FuncSignature& sign) { return addCall(X86Inst::kIdCall, label, sign); }
267
  //! \overload
268
  ASMJIT_INLINE CCFuncCall* call(const Imm& dst, const FuncSignature& sign) { return addCall(X86Inst::kIdCall, dst, sign); }
269
  //! \overload
270
  ASMJIT_INLINE CCFuncCall* call(uint64_t dst, const FuncSignature& sign) { return addCall(X86Inst::kIdCall, Imm(dst), sign); }
271

272
273
  //! Return.
  ASMJIT_INLINE CCFuncRet* ret() { return addRet(Operand(), Operand()); }
274
  //! \overload
275
  ASMJIT_INLINE CCFuncRet* ret(const X86Gp& o0) { return addRet(o0, Operand()); }
276
  //! \overload
277
  ASMJIT_INLINE CCFuncRet* ret(const X86Gp& o0, const X86Gp& o1) { return addRet(o0, o1); }
278
  //! \overload
279
  ASMJIT_INLINE CCFuncRet* ret(const X86Xmm& o0) { return addRet(o0, Operand()); }
280
  //! \overload
281
  ASMJIT_INLINE CCFuncRet* ret(const X86Xmm& o0, const X86Xmm& o1) { return addRet(o0, o1); }
282
283
284
285
286
287
288
};

//! \}

} // asmjit namespace

// [Api-End]
289
#include "../asmjit_apiend.h"
290
291
292
293

// [Guard]
#endif // !ASMJIT_DISABLE_COMPILER
#endif // _ASMJIT_X86_X86COMPILER_H