asmjit.h 14.7 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.

// [Guard]
#ifndef _ASMJIT_ASMJIT_H
#define _ASMJIT_ASMJIT_H

// ============================================================================
// [asmjit_mainpage]
// ============================================================================

//! @mainpage
//!
//! AsmJit - Complete x86/x64 JIT and Remote Assembler for C++.
//!
//! AsmJit is a complete JIT and remote assembler for C++ language. It can
//! generate native code for x86 and x64 architectures having support for
//! a full instruction set, from legacy MMX to the newest AVX2. It has a
//! type-safe API that allows C++ compiler to do a semantic checks at
//! compile-time even before the assembled code is generated or run.
//!
//! AsmJit is not a virtual machine (VM). It doesn't have functionality to
//! implement VM out of the box; however, it can be be used as a JIT backend
//! for your own VM. The usage of AsmJit is not limited at all; it's suitable
//! for multimedia, VM backends or remote code generation.
//!
//! @section AsmJit_Concepts Code Generation Concepts
//!
//! AsmJit has two completely different code generation concepts. The difference
//! is in how the code is generated. The first concept, also referred as the low
//! level concept, is called 'Assembler' and it's the same as writing RAW
//! assembly by using physical registers directly. In this case AsmJit does only
//! instruction encoding, verification and relocation.
//!
//! The second concept, also referred as the high level concept, is called
//! 'Compiler'. Compiler lets you use virtually unlimited number of registers
//! (called variables) significantly simplifying the code generation process.
//! Compiler allocates these virtual registers to physical registers after the
//! code generation is done. This requires some extra effort - Compiler has to
//! generate information for each node (instruction, function declaration,
//! function call) in the code, perform a variable liveness analysis and
//! translate the code having variables into code having only registers.
//!
//! In addition, Compiler understands functions and function calling conventions.
//! It has been designed in a way that the code generated is always a function
//! having prototype like in a programming language. By having a function
//! prototype the Compiler is able to insert prolog and epilog to a function
//! being generated and it is able to call a function inside a generated one.
//!
//! There is no conclusion on which concept is better. Assembler brings full
//! control on how the code is generated, while Compiler makes the generation
//! more portable.
//!
//! @section AsmJit_Main_CodeGeneration Code Generation
//!
//! - \ref asmjit_base_general "Assembler core" - Operands, intrinsics and low-level assembler.
//! - \ref asmjit_compiler "Compiler" - High level code generation.
//! - \ref asmjit_cpuinfo "Cpu Information" - Get information about host processor.
//! - \ref asmjit_logging "Logging" - Logging and error handling.
//! - \ref AsmJit_MemoryManagement "Memory Management" - Virtual memory management.
//!
//! @section AsmJit_Main_HomePage AsmJit Homepage
//!
//! - https://github.com/kobalicek/asmjit

// ============================================================================
// [asmjit_base]
// ============================================================================

//! \defgroup asmjit_base AsmJit
//!
//! \brief AsmJit.

// ============================================================================
// [asmjit_base_general]
// ============================================================================

//! \defgroup asmjit_base_general AsmJit General API
//! \ingroup asmjit_base
//!
//! \brief AsmJit general API.
//!
//! Contains all `asmjit` classes and helper functions that are architecture
//! independent or abstract. Abstract classes are implemented by the backend,
//! for example `Assembler` is implemented by `X86Assembler`.
//!
//! - See `Assembler` for low level code generation documentation.
//! - See `Compiler` for high level code generation documentation.
//! - See `Operand` for operand's overview.
//!
//! Logging and Error Handling
//! --------------------------
//!
//! AsmJit contains robust interface that can be used to log the generated code
//! and to handle possible errors. Base logging interface is defined in `Logger`
//! class that is abstract and can be overridden. AsmJit contains two loggers
//! that can be used out of the box - `FileLogger` that logs into a pure C
//! `FILE*` stream and `StringLogger` that just concatenates all log messages
//! by using a `StringBuilder` class.
//!
//! The following snippet shows how to setup a logger that logs to `stderr`:
//!
//! ~~~
//! // `FileLogger` instance.
//! FileLogger logger(stderr);
//!
//! // `Compiler` or any other `CodeGen` interface.
//! host::Compiler c;
//!
//! // use `setLogger` to replace the `CodeGen` logger.
//! c.setLogger(&logger);
//! ~~~
//!
//! \sa \ref Logger, \ref FileLogger, \ref StringLogger.

// ============================================================================
// [asmjit_base_compiler]
// ============================================================================

//! \defgroup asmjit_base_compiler AsmJit Compiler
//! \ingroup asmjit_base
//!
//! \brief AsmJit code-tree used by Compiler.
//!
//! AsmJit intermediate code-tree is a double-linked list that is made of nodes
//! that represent assembler instructions, directives, labels and high-level
//! constructs compiler is using to represent functions and function calls. The
//! node list can only be used together with \ref Compiler.
//!
//! TODO

// ============================================================================
// [asmjit_base_util]
// ============================================================================

//! \defgroup asmjit_base_util AsmJit Utilities
//! \ingroup asmjit_base
//!
//! \brief AsmJit utility classes.
//!
//! AsmJit contains numerous utility classes that are needed by the library
//! itself. The most useful ones have been made public and are now exported.
//!
//! POD Containers
//! --------------
//!
//! POD containers are used by AsmJit to manage its own data structures. The
//! following classes can be used by AsmJit consumers:
//!
//!   - \ref PodVector - Simple growing array-like container for POD data.
//!   - \ref StringBuilder - Simple string builder that can append string
//!     and integers.
//!
//! Zone Memory Allocator
//! ---------------------
//!
//! Zone memory allocator is an incremental memory allocator that can be used
//! to allocate data of short life-time. It has much better performance
//! characteristics than all other allocators, because the only thing it can do
//! is to increment a pointer and return its previous address. See \ref Zone
//! for more details.
//!
//! CPU Ticks
//! ---------
//!
//! CPU Ticks is a simple helper that can be used to do basic benchmarks. See
//! \ref CpuTicks class for more details.
//!
//! Integer Utilities
//! -----------------
//!
//! Integer utilities are all implemented by a static class \ref IntUtil.
//! There are utilities for bit manipulation and bit counting, utilities to get
//! an integer minimum / maximum and various other helpers required to perform
//! alignment checks and binary casting from float to integer and vica versa.
//!
//! Vector Utilities
//! ----------------
//!
//! SIMD code generation often requires to embed constants after each function
//! or a block of functions generated. AsmJit contains classes `Vec64`,
//! `Vec128` and `Vec256` that can be used to prepare data useful when
//! generating SIMD code.
//!
//! X86/X64 code generator contains member functions `dmm`, `dxmm` and `dymm`
//! which can be used to embed 64-bit, 128-bit and 256-bit data structures into
//! machine code (both assembler and compiler are supported).
//!
//! \note Compiler contains a constant pool, which should be used instead of
//! embedding constants manually after the function body.

// ============================================================================
// [asmjit_x86]
// ============================================================================

//! \defgroup asmjit_x86 X86/X64
//!
//! \brief X86/X64 module

// ============================================================================
// [asmjit_x86_general]
// ============================================================================

//! \defgroup asmjit_x86_general X86/X64 General API
//! \ingroup asmjit_x86
//!
//! \brief X86/X64 general API.
//!
//! X86/X64 Registers
//! -----------------
//!
//! There are static objects that represents X86 and X64 registers. They can
//! be used directly (like `eax`, `mm`, `xmm`, ...) or created through
//! these functions:
//!
//! - `asmjit::gpb_lo()` - Get Gpb-lo register.
//! - `asmjit::gpb_hi()` - Get Gpb-hi register.
//! - `asmjit::gpw()` - Get Gpw register.
//! - `asmjit::gpd()` - Get Gpd register.
//! - `asmjit::gpq()` - Get Gpq Gp register.
//! - `asmjit::gpz()` - Get Gpd/Gpq register.
//! - `asmjit::fp()`  - Get Fp register.
//! - `asmjit::mm()`  - Get Mm register.
//! - `asmjit::xmm()` - Get Xmm register.
//! - `asmjit::ymm()` - Get Ymm register.
//!
//! X86/X64 Addressing
//! ------------------
//!
//! X86 and x64 architectures contains several addressing modes and most ones
//! are possible with AsmJit library. Memory represents are represented by
//! `BaseMem` class. These functions are used to make operands that represents
//! memory addresses:
//!
238
239
240
241
242
243
244
245
246
//! - `asmjit::ptr()`       - Address size not specified.
//! - `asmjit::byte_ptr()`  - 1 byte.
//! - `asmjit::word_ptr()`  - 2 bytes (Gpw size).
//! - `asmjit::dword_ptr()` - 4 bytes (Gpd size).
//! - `asmjit::qword_ptr()` - 8 bytes (Gpq/Mm size).
//! - `asmjit::tword_ptr()` - 10 bytes (FPU).
//! - `asmjit::oword_ptr()` - 16 bytes (Xmm size).
//! - `asmjit::yword_ptr()` - 32 bytes (Ymm size).
//! - `asmjit::zword_ptr()` - 64 bytes (Zmm size).
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
//!
//! Most useful function to make pointer should be `asmjit::ptr()`. It creates
//! pointer to the target with unspecified size. Unspecified size works in all
//! intrinsics where are used registers (this means that size is specified by
//! register operand or by instruction itself). For example `asmjit::ptr()`
//! can't be used with `Assembler::inc()` instruction. In this case size must
//! be specified and it's also reason to make difference between pointer sizes.
//!
//! Supported are simple address forms `[base + displacement]` and complex
//! address forms `[base + index * scale + displacement]`.
//!
//! X86/X64 Immediates
//! ------------------
//!
//! Immediate values are constants thats passed directly after instruction
//! opcode. To create such value use `imm()` or `imm_u()` methods to create
//! signed or unsigned immediate value.
//!
//! X86/X64 CPU Information
//! -----------------------
//!
//! The CPUID instruction can be used to get an exhaustive information about
//! the host X86/X64 processor. AsmJit contains utilities that can get the most
//! important information related to the features supported by the CPU and the
//! host operating system, in addition to host processor name and number of
//! cores. Class `X86CpuInfo` extends `CpuInfo` and provides functionality
//! specific to X86 and X64.
//!
//! By default AsmJit queries the CPU information after the library is loaded
//! and the queried information is reused by all instances of `JitRuntime`.
//! The global instance of `X86CpuInfo` can't be changed, because it will affect
//! the code generation of all `Runtime`s. If there is a need to have a
//! specific CPU information which contains modified features or processor
//! vendor it's possible by creating a new instance of `X86CpuInfo` and setting
//! up its members. `X86CpuUtil::detect` can be used to detect CPU features into
//! an existing `X86CpuInfo` instance - it may become handly if only one property
//! has to be turned on/off.
//!
//! If the high-level interface `X86CpuInfo` offers is not enough there is also
//! `X86CpuUtil::callCpuId` helper that can be used to call CPUID instruction
//! with a given parameters and to consume the output.
//!
//! Cpu detection is important when generating a JIT code that may or may not
//! use certain CPU features. For example there used to be a SSE/SSE2 detection
//! in the past and today there is often AVX/AVX2 detection.
//!
//! The example below shows how to detect SSE2:
//!
//! ~~~
//! using namespace asmjit;
//!
//! // Get `X86CpuInfo` global instance.
//! const X86CpuInfo* cpuInfo = X86CpuInfo::getHost();
//!
301
//! if (cpuInfo->hasFeature(kX86CpuFeatureSSE2)) {
302
303
//!   // Processor has SSE2.
//! }
304
//! else if (cpuInfo->hasFeature(kX86CpuFeatureMMX)) {
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
//!   // Processor doesn't have SSE2, but has MMX.
//! }
//! else {
//!   // Processor is archaic; it's a wonder AsmJit works here!
//! }
//! ~~~
//!
//! The next example shows how to call `CPUID` directly:
//!
//! ~~~
//! using namespace asmjit;
//!
//! // Call cpuid, first two arguments are passed in Eax/Ecx.
//! X86CpuId out;
//! X86CpuUtil::callCpuId(0, 0, &out);
//!
//! // If Eax argument is 0, Ebx, Ecx and Edx registers are filled with a cpu vendor.
//! char cpuVendor[13];
//! ::memcpy(cpuVendor, &out.ebx, 4);
//! ::memcpy(cpuVendor + 4, &out.edx, 4);
//! ::memcpy(cpuVendor + 8, &out.ecx, 4);
//! vendor[12] = '\0';
//!
//! // Print a CPU vendor retrieved from CPUID.
//! ::printf("%s", cpuVendor);
//! ~~~

// ============================================================================
// [asmjit_x86_compiler]
// ============================================================================

//! \defgroup asmjit_x86_compiler X86/X64 Code-Tree
//! \ingroup asmjit_x86
//!
//! \brief X86/X64 code-tree and helpers.

// ============================================================================
// [asmjit_x86_inst]
// ============================================================================

//! \defgroup asmjit_x86_inst X86/X64 Instructions
//! \ingroup asmjit_x86
//!
//! \brief X86/X64 low-level instruction definitions.

// ============================================================================
// [asmjit_x86_util]
// ============================================================================

//! \defgroup asmjit_x86_util X86/X64 Utilities
//! \ingroup asmjit_x86
//!
//! \brief X86/X64 utility classes.

// ============================================================================
// [asmjit_contrib]
// ============================================================================

//! \defgroup asmjit_contrib Contributions
//!
//! \brief Contributions.

// [Dependencies - Base]
#include "base.h"

// [Dependencies - X86/X64]
#if defined(ASMJIT_BUILD_X86) || defined(ASMJIT_BUILD_X64)
#include "x86.h"
#endif // ASMJIT_BUILD_X86 || ASMJIT_BUILD_X64

// [Dependencies - Host]
#include "host.h"

// [Guard]
#endif // _ASMJIT_ASMJIT_H