- Minor reorganization of source code (split defs to operand and instruction info).

- Added JECXZ instruction.
- Doxyfile is now in project root.
- Documentation updates.
This commit is contained in:
kobalicek
2014-05-10 21:19:50 +02:00
parent bd1a5facb8
commit 1a73e65534
69 changed files with 9451 additions and 5174 deletions

View File

@@ -222,8 +222,6 @@ AsmJit_AddSource(ASMJIT_SRC asmjit/base
cpuinfo.h
cputicks.cpp
cputicks.h
defs.cpp
defs.h
error.cpp
error.h
func.cpp
@@ -234,6 +232,8 @@ AsmJit_AddSource(ASMJIT_SRC asmjit/base
lock.h
logger.cpp
logger.h
operand.cpp
operand.h
podlist.h
podvector.cpp
podvector.h
@@ -257,10 +257,14 @@ AsmJit_AddSource(ASMJIT_SRC asmjit/x86
x86context_p.h
x86cpuinfo.cpp
x86cpuinfo.h
x86defs.cpp
x86defs.h
x86func.cpp
x86func.h
x86inst.cpp
x86inst.h
x86operand.cpp
x86operand.h
x86util.cpp
x86util.h
)
AsmJit_AddSource(ASMJIT_SRC asmjit/contrib

236
Doxyfile Normal file
View File

@@ -0,0 +1,236 @@
# Doxyfile 1.8.7
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "AsmJit"
PROJECT_NUMBER = "1.1"
PROJECT_BRIEF = "Complete Remote and JIT Assembler for x86/x64"
OUTPUT_DIRECTORY = .
CREATE_SUBDIRS = NO
ALLOW_UNICODE_NAMES = NO
OUTPUT_LANGUAGE = English
FULL_PATH_NAMES = YES
STRIP_FROM_PATH =
STRIP_FROM_INC_PATH =
SHORT_NAMES = NO
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
QT_AUTOBRIEF = NO
JAVADOC_AUTOBRIEF = YES
MULTILINE_CPP_IS_BRIEF = YES
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
INHERIT_DOCS = YES
TAB_SIZE = 2
MARKDOWN_SUPPORT = YES
AUTOLINK_SUPPORT = NO
IDL_PROPERTY_SUPPORT = NO
SEPARATE_MEMBER_PAGES = NO
DISTRIBUTE_GROUP_DOC = NO
SUBGROUPING = YES
INLINE_GROUPED_CLASSES = NO
INLINE_SIMPLE_STRUCTS = NO
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = NO
EXTRACT_PRIVATE = NO
EXTRACT_PACKAGE = NO
EXTRACT_STATIC = NO
EXTRACT_LOCAL_CLASSES = NO
HIDE_UNDOC_CLASSES = YES
HIDE_UNDOC_MEMBERS = NO
HIDE_FRIEND_COMPOUNDS = YES
HIDE_IN_BODY_DOCS = YES
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = NO
# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
# their full class and namespace scopes in the documentation. If set to YES the
# scope will be hidden.
# The default value is: NO.
HIDE_SCOPE_NAMES = NO
SHOW_INCLUDE_FILES = NO
SHOW_GROUPED_MEMB_INC = NO
INLINE_INFO = YES
SORT_MEMBER_DOCS = NO
SORT_BRIEF_DOCS = NO
SORT_GROUP_NAMES = NO
SORT_BY_SCOPE_NAME = YES
STRICT_PROTO_MATCHING = NO
GENERATE_TODOLIST = NO
GENERATE_TESTLIST = NO
GENERATE_BUGLIST = NO
GENERATE_DEPRECATEDLIST= NO
MAX_INITIALIZER_LINES = 0
SHOW_USED_FILES = NO
SHOW_FILES = NO
SHOW_NAMESPACES = NO
#---------------------------------------------------------------------------
# Configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = YES
WARNINGS = YES
WARN_IF_UNDOCUMENTED = NO
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
#---------------------------------------------------------------------------
# Configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = src/asmjit
INPUT_ENCODING = UTF-8
RECURSIVE = YES
EXCLUDE =
USE_MDFILE_AS_MAINPAGE = README.md
#---------------------------------------------------------------------------
# Configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = NO
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
SOURCE_TOOLTIPS = YES
VERBATIM_HEADERS = NO
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = NO
#---------------------------------------------------------------------------
# Configuration options related to outputs
#---------------------------------------------------------------------------
GENERATE_HTML = YES
GENERATE_LATEX = NO
GENERATE_RTF = NO
GENERATE_MAN = NO
GENERATE_XML = YES
XML_OUTPUT = build_xml
XML_PROGRAMLISTING = NO
HTML_OUTPUT = build_doc
HTML_FILE_EXTENSION = .html
LAYOUT_FILE = tools/doc-layout.xml
HTML_HEADER = tools/doc-header.html
HTML_FOOTER = tools/doc-footer.html
HTML_STYLESHEET = tools/doc-style.css
HTML_EXTRA_STYLESHEET =
HTML_EXTRA_FILES =
HTML_COLORSTYLE_HUE = 220
HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_GAMMA = 80
HTML_TIMESTAMP = NO
HTML_DYNAMIC_SECTIONS = NO
HTML_INDEX_NUM_ENTRIES = 0
SEARCHENGINE = NO
#---------------------------------------------------------------------------
# Configuration options related to the CHM output
#---------------------------------------------------------------------------
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
# Windows.
#
# The HTML Help Workshop contains a compiler that can convert all HTML output
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
# files are now used as the Windows 98 help format, and will replace the old
# Windows help format (.hlp) on all Windows platforms in the future. Compressed
# HTML files also contain an index, a table of contents, and you can search for
# words in the documentation. The HTML workshop also contains a viewer for
# compressed HTML files.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_HTMLHELP = NO
# The CHM_FILE tag can be used to specify the file name of the resulting .chm
# file. You can add a path in front of the file if the result should not be
# written to the html output directory.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_FILE =
# The HHC_LOCATION tag can be used to specify the location (absolute path
# including file name) of the HTML help compiler ( hhc.exe). If non-empty
# doxygen will try to run the HTML help compiler on the generated index.hhp.
# The file has to be specified with full path.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
HHC_LOCATION =
# The BINARY_TOC flag controls whether a binary table of contents is generated (
# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
# enables the Previous and Next buttons.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
BINARY_TOC = NO
# The TOC_EXPAND flag can be set to YES to add extra items for group members to
# the table of contents of the HTML help documentation and to the tree view.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
TOC_EXPAND = NO
DISABLE_INDEX = NO
GENERATE_TREEVIEW = NO
ENUM_VALUES_PER_LINE = 0
TREEVIEW_WIDTH = 250
EXT_LINKS_IN_WINDOW = NO
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = NO
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
PREDEFINED = ASMJIT_DOCGEN \
ASMJIT_BUILD_X86 \
ASMJIT_BUILD_X64 \
ASMJIT_API
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = NO
CLASS_GRAPH = NO

View File

@@ -29,7 +29,7 @@ Features
* Built-in CPU detection,
* Virtual Memory management,
* Pretty logging and error handling,
* Small and embeddable, around 150kB compiled,
* Small and embeddable, around 150-200kB compiled,
* Zero dependencies, not even STL or RTTI.
Supported Environments
@@ -46,7 +46,7 @@ Supported Environments
* BorlandC++
* GNU (3.4.X+, 4.0+, MinGW)
* MSVC (VS2005, VS2008, VS2010)
* MSVC (VS2005+)
* Other compilers require testing
### Backends

View File

@@ -88,7 +88,7 @@ static void blend(asmjit::host::Compiler& c) {
c.psrlw(a0, 8);
c.punpcklbw(x0, cZero);
c.pshuflw(a0, a0, mm_shuffle(1, 1, 1, 1));
c.pshuflw(a0, a0, X86Util::mmShuffle(1, 1, 1, 1));
c.punpcklbw(y0, cZero);
c.pmullw(x0, a0);
@@ -136,8 +136,8 @@ static void blend(asmjit::host::Compiler& c) {
c.punpckhbw(x1, cZero);
c.punpckhwd(a1, a1);
c.pshufd(a0, a0, mm_shuffle(3, 3, 1, 1));
c.pshufd(a1, a1, mm_shuffle(3, 3, 1, 1));
c.pshufd(a0, a0, X86Util::mmShuffle(3, 3, 1, 1));
c.pshufd(a1, a1, X86Util::mmShuffle(3, 3, 1, 1));
c.pmullw(x0, a0);
c.pmullw(x1, a1);
@@ -166,7 +166,7 @@ static void blend(asmjit::host::Compiler& c) {
c.endFunc();
// Data.
c.align(16);
c.align(kAlignData, 16);
c.bind(L_Data);
c.dxmm(XmmData::fromSw(0x0080));
c.dxmm(XmmData::fromSw(0x0101));

View File

@@ -268,6 +268,87 @@ static void opcode(asmjit::host::Assembler& a) {
a.xor_(intptr_gp0, gp1);
a.xor_(intptr_gp0, 0);
// Label...Jcc/Jecxz/Jmp.
{
a.nop();
Label L(a);
a.bind(L);
a.ja(L);
a.jae(L);
a.jb(L);
a.jbe(L);
a.jc(L);
a.je(L);
a.jg(L);
a.jge(L);
a.jl(L);
a.jle(L);
a.jna(L);
a.jnae(L);
a.jnb(L);
a.jnbe(L);
a.jnc(L);
a.jne(L);
a.jng(L);
a.jnge(L);
a.jnl(L);
a.jnle(L);
a.jno(L);
a.jnp(L);
a.jns(L);
a.jnz(L);
a.jo(L);
a.jp(L);
a.jpe(L);
a.jpo(L);
a.js(L);
a.jz(L);
a.jecxz(ecx, L);
a.jmp(L);
}
// Jcc/Jecxz/Jmp...Label.
{
a.nop();
Label L(a);
a.ja(L);
a.jae(L);
a.jb(L);
a.jbe(L);
a.jc(L);
a.je(L);
a.jg(L);
a.jge(L);
a.jl(L);
a.jle(L);
a.jna(L);
a.jnae(L);
a.jnb(L);
a.jnbe(L);
a.jnc(L);
a.jne(L);
a.jng(L);
a.jnge(L);
a.jnl(L);
a.jnle(L);
a.jno(L);
a.jnp(L);
a.jns(L);
a.jnz(L);
a.jo(L);
a.jp(L);
a.jpe(L);
a.jpo(L);
a.js(L);
a.jz(L);
a.jecxz(ecx, L);
a.jmp(L);
a.bind(L);
}
// Fpu.
a.nop();

View File

@@ -59,7 +59,7 @@ int main(int argc, char* argv[]) {
printf(" asmjit::LabelData : %u\n", static_cast<uint32_t>(sizeof(LabelData)));
printf(" asmjit::RelocData : %u\n", static_cast<uint32_t>(sizeof(RelocData)));
printf("\n");
printf(" asmjit::BaseNode : %u\n", static_cast<uint32_t>(sizeof(BaseNode)));
printf(" asmjit::Node : %u\n", static_cast<uint32_t>(sizeof(Node)));
printf(" asmjit::AlignNode : %u\n", static_cast<uint32_t>(sizeof(AlignNode)));
printf(" asmjit::CallNode : %u\n", static_cast<uint32_t>(sizeof(CallNode)));
printf(" asmjit::CommentNode : %u\n", static_cast<uint32_t>(sizeof(CommentNode)));

View File

@@ -56,19 +56,315 @@
//!
//! @section AsmJit_Main_CodeGeneration Code Generation
//!
//! - @ref asmjit_base "Assembler core" - Operands, intrinsics and low-level assembler.
//! - @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_Configuration Configuration, Definitions and Utilities
//!
//! - @ref asmjit_config "Configuration" - Macros used to configure AsmJit.
//!
//! @section AsmJit_Main_HomePage AsmJit Homepage
//!
//! - http://code.google.com/p/asmjit/
//! - https://github.com/kobalicekp/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 `BaseAssembler` is implemented by `x86x64::X86X64Assembler`.
//!
//! - See `BaseAssembler` for low level code generation documentation.
//! - See `BaseCompiler` 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_tree]
// ============================================================================
//! \defgroup asmjit_base_tree AsmJit Code-Tree
//! \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 BaseCompiler.
//!
//! 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 `Vec64Data`,
//! `Vec128Data` and `Vec256Data` 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_x86x64]
// ============================================================================
//! \defgroup asmjit_x86x64 X86/X64
//!
//! \brief X86/X64 module
// ============================================================================
// [asmjit_x86x64_general]
// ============================================================================
//! \defgroup asmjit_x86x64_general X86/X64 General API
//! \ingroup asmjit_x86x64
//!
//! \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:
//!
//! - `asmjit::ptr()`
//! - `asmjit::byte_ptr()`
//! - `asmjit::word_ptr()`
//! - `asmjit::dword_ptr()`
//! - `asmjit::qword_ptr()`
//! - `asmjit::tword_ptr()`
//! - `asmjit::oword_ptr()`
//! - `asmjit::yword_ptr()`
//! - `asmjit::intptr_ptr()`
//!
//! 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 @c asmjit::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 @c asmjit::imm() or @c asmjit::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 `CpuInfo` extends `BaseCpuInfo` 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 `CpuInfo` 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 `CpuInfo` and setting
//! up its members. `CpuUtil::detect` can be used to detect CPU features into
//! an existing `CpuInfo` instance - it may become handly if only one property
//! has to be turned on/off.
//!
//! If the high-level interface `CpuInfo` offers is not enough there is also
//! `CpuUtil::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;
//! using namespace asmjit::host;
//!
//! // Get `CpuInfo` global instance.
//! const CpuInfo* cpuInfo = CpuInfo::getHost();
//!
//! if (cpuInfo->hasFeature(kCpuFeatureSse2)) {
//! // Processor has SSE2.
//! }
//! else if (cpuInfo->hasFeature(kCpuFeatureMmx)) {
//! // 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.
//! CpuId out;
//! CpuUtil::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_x86x64_tree]
// ============================================================================
//! \defgroup asmjit_x86x64_tree X86/X64 Code-Tree
//! \ingroup asmjit_x86x64
//!
//! \brief X86/X64 code-tree and helpers.
// ============================================================================
// [asmjit_x86x64_inst]
// ============================================================================
//! \defgroup asmjit_x86x64_inst X86/X64 Instructions
//! \ingroup asmjit_x86x64
//!
//! \brief X86/X64 low-level instruction definitions.
// ============================================================================
// [asmjit_x86x64_util]
// ============================================================================
//! \defgroup asmjit_x86x64_util X86/X64 Utilities
//! \ingroup asmjit_x86x64
//!
//! \brief X86/X64 utility classes.
// ============================================================================
// [asmjit_contrib]
// ============================================================================
//! \defgroup asmjit_contrib Contributions
//!
//! \brief Contributions.
// [Dependencies - Base]
#include "base.h"

View File

@@ -8,193 +8,7 @@
#ifndef _ASMJIT_BASE_H
#define _ASMJIT_BASE_H
// ============================================================================
// [asmjit_base]
// ============================================================================
//! @defgroup asmjit_base Base
//!
//! @brief AsmJit Base API.
//!
//! Contains all `asmjit` classes and helper functions that are architecture
//! independent or abstract. Abstract classes are implemented by the backend,
//! for example `BaseAssembler` is implemented by `x86x64::X86X64Assembler`.
//!
//! - See `BaseAssembler` for low level code generation documentation.
//! - See `BaseCompiler` for high level code generation documentation.
//! - See `Operand` for operand's overview.
//!
//! @section AsmJit_Core_Registers 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.
//!
//! @section AsmJit_Core_Addressing 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:
//!
//! - `asmjit::ptr()`
//! - `asmjit::byte_ptr()`
//! - `asmjit::word_ptr()`
//! - `asmjit::dword_ptr()`
//! - `asmjit::qword_ptr()`
//! - `asmjit::tword_ptr()`
//! - `asmjit::oword_ptr()`
//! - `asmjit::yword_ptr()`
//! - `asmjit::intptr_ptr()`
//!
//! 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 @c asmjit::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 (register + displacement) and complex
//! address forms (register + (register << shift) + displacement).
//!
//! @section AsmJit_Core_Immediates Immediates
//!
//! Immediate values are constants thats passed directly after instruction
//! opcode. To create such value use @c asmjit::imm() or @c asmjit::imm_u()
//! methods to create signed or unsigned immediate value.
//!
//! @sa @c asmjit::BaseCompiler.
// ============================================================================
// [asmjit_base_globals]
// ============================================================================
//! @defgroup asmjit_base_globals Globals
//! @ingroup asmjit_base
//!
//! @brief Global definitions, macros and functions.
// ============================================================================
// [asmjit_base_codegen]
// ============================================================================
//! @defgroup asmjit_base_codegen Code Generation (Base)
//! @ingroup asmjit_base
//!
//! @brief Low-level and high-level code generation.
// ============================================================================
// [asmjit_base_cpu_info]
// ============================================================================
//! @defgroup asmjit_base_cpu_info CPU Information (Base)
//! @ingroup asmjit_base
//!
//! @brief CPU Information Interface, platform neutral.
// ============================================================================
// [asmjit_base_logging_and_errors]
// ============================================================================
//! @defgroup asmjit_base_logging_and_errors Logging and Error Handling
//! @ingroup asmjit_base
//!
//! @brief 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 `FILE*`
//! and `StringLogger` that just concatenates all log messages without sending
//! them to a stream.
//!
//! 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_util]
// ============================================================================
//! @defgroup asmjit_base_util Utilities
//! @ingroup asmjit_base
//!
//! @brief Utilities inside AsmJit made public.
//!
//! 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
//! --------------
//!
//! TODO: Documentation
//!
//! String Builder
//! --------------
//!
//! TODO: Documentation
//!
//! Integer Utilities
//! -----------------
//!
//! TODO: Documentation
//!
//! Zone Memory Allocator
//! ---------------------
//!
//! TODO: Documentation
//!
//! CPU Ticks
//! ---------
//!
//! TODO: Documentation
// ============================================================================
// [asmjit_base_vectypes]
// ============================================================================
//! @defgroup asmjit_base_vectypes Vector Types
//! @ingroup asmjit_base
//!
//! @brief Vector types can be used to create a data which is stored in the
//! machine code.
// ============================================================================
// [asmjit::]
// ============================================================================
//! @namespace asmjit
//! Main AsmJit library namespace.
//!
//! There are not other namespaces used in AsmJit library.
// ============================================================================
// [Dependencies - AsmJit]
// ============================================================================
#include "build.h"
#include "base/assembler.h"
@@ -203,15 +17,16 @@
#include "base/constpool.h"
#include "base/cpuinfo.h"
#include "base/cputicks.h"
#include "base/defs.h"
#include "base/error.h"
#include "base/func.h"
#include "base/globals.h"
#include "base/intutil.h"
#include "base/lock.h"
#include "base/logger.h"
#include "base/operand.h"
#include "base/podlist.h"
#include "base/podvector.h"
#include "base/runtime.h"
#include "base/string.h"
#include "base/vectypes.h"
#include "base/vmem.h"

View File

@@ -10,9 +10,9 @@
// [Dependencies - AsmJit]
#include "../base/codegen.h"
#include "../base/defs.h"
#include "../base/error.h"
#include "../base/logger.h"
#include "../base/operand.h"
#include "../base/podlist.h"
#include "../base/podvector.h"
#include "../base/runtime.h"
@@ -23,14 +23,59 @@
namespace asmjit {
//! @addtogroup asmjit_base_codegen
//! @{
//! \addtogroup asmjit_base_general
//! \{
// ============================================================================
// [asmjit::kInstCode]
// ============================================================================
//! Instruction codes (stub).
ASMJIT_ENUM(kInstCode) {
//! No instruction.
kInstNone = 0
};
// ============================================================================
// [asmjit::kInstOptions]
// ============================================================================
//! Instruction options (stub).
ASMJIT_ENUM(kInstOptions) {
//! No instruction options.
kInstOptionNone = 0x00,
//! Emit short form of the instruction.
//!
//! X86/X64:
//!
//! Short form is mostly related to jmp and jcc instructions, but can be used
//! by other instructions supporting 8-bit or 32-bit immediates. This option
//! can be dangerous if the short jmp/jcc is required, but not encodable due
//! to large displacement, in such case an error happens and the whole
//! assembler/compiler stream is unusable.
kInstOptionShortForm = 0x01,
//! Emit long form of the instruction.
//!
//! X86/X64:
//!
//! Long form is mosrlt related to jmp and jcc instructions, but like the
//! `kInstOptionShortForm` option it can be used by other instructions
//! supporting both 8-bit and 32-bit immediates.
kInstOptionLongForm = 0x02,
//! Condition is likely to be taken (instruction).
kInstOptionTaken = 0x04,
//! Condition is unlikely to be taken (instruction).
kInstOptionNotTaken = 0x08
};
// ============================================================================
// [asmjit::LabelLink]
// ============================================================================
//! @internal
//! \internal
//!
//! Data structure used to link linked-labels.
struct LabelLink {
@@ -48,7 +93,7 @@ struct LabelLink {
// [asmjit::LabelData]
// ============================================================================
//! @internal
//! \internal
//!
//! Label data.
struct LabelData {
@@ -62,7 +107,7 @@ struct LabelData {
// [asmjit::RelocData]
// ============================================================================
//! @internal
//! \internal
//!
//! Code relocation data (relative vs absolute addresses).
//!
@@ -182,61 +227,61 @@ struct BaseAssembler : public CodeGen {
//! Reserve the internal buffer to at least `n` bytes.
ASMJIT_API Error _reserve(size_t n);
//! Set byte at position `pos`.
//! Get BYTE at position `pos`.
ASMJIT_INLINE uint8_t getByteAt(size_t pos) const {
ASMJIT_ASSERT(pos + 1 <= (size_t)(_end - _buffer));
return *reinterpret_cast<const uint8_t*>(_buffer + pos);
}
//! Set word at position `pos`.
//! Get WORD at position `pos`.
ASMJIT_INLINE uint16_t getWordAt(size_t pos) const {
ASMJIT_ASSERT(pos + 2 <= (size_t)(_end - _buffer));
return *reinterpret_cast<const uint16_t*>(_buffer + pos);
}
//! Set dword at position `pos`.
//! Get DWORD at position `pos`.
ASMJIT_INLINE uint32_t getDWordAt(size_t pos) const {
ASMJIT_ASSERT(pos + 4 <= (size_t)(_end - _buffer));
return *reinterpret_cast<const uint32_t*>(_buffer + pos);
}
//! Set qword at position `pos`.
//! Get QWORD at position `pos`.
ASMJIT_INLINE uint64_t getQWordAt(size_t pos) const {
ASMJIT_ASSERT(pos + 8 <= (size_t)(_end - _buffer));
return *reinterpret_cast<const uint64_t*>(_buffer + pos);
}
//! Set int32_t at position `pos`.
//! Get int32_t at position `pos`.
ASMJIT_INLINE int32_t getInt32At(size_t pos) const {
ASMJIT_ASSERT(pos + 4 <= (size_t)(_end - _buffer));
return *reinterpret_cast<const int32_t*>(_buffer + pos);
}
//! Set uint32_t at position `pos`.
//! Get uint32_t at position `pos`.
ASMJIT_INLINE uint32_t getUInt32At(size_t pos) const {
ASMJIT_ASSERT(pos + 4 <= (size_t)(_end - _buffer));
return *reinterpret_cast<const uint32_t*>(_buffer + pos);
}
//! Set byte at position `pos`.
//! Set BYTE at position `pos`.
ASMJIT_INLINE void setByteAt(size_t pos, uint8_t x) {
ASMJIT_ASSERT(pos + 1 <= (size_t)(_end - _buffer));
*reinterpret_cast<uint8_t*>(_buffer + pos) = x;
}
//! Set word at position `pos`.
//! Set WORD at position `pos`.
ASMJIT_INLINE void setWordAt(size_t pos, uint16_t x) {
ASMJIT_ASSERT(pos + 2 <= (size_t)(_end - _buffer));
*reinterpret_cast<uint16_t*>(_buffer + pos) = x;
}
//! Set dword at position `pos`.
//! Set DWORD at position `pos`.
ASMJIT_INLINE void setDWordAt(size_t pos, uint32_t x) {
ASMJIT_ASSERT(pos + 4 <= (size_t)(_end - _buffer));
*reinterpret_cast<uint32_t*>(_buffer + pos) = x;
}
//! Set qword at position `pos`.
//! Set QWORD at position `pos`.
ASMJIT_INLINE void setQWordAt(size_t pos, uint64_t x) {
ASMJIT_ASSERT(pos + 8 <= (size_t)(_end - _buffer));
*reinterpret_cast<uint64_t*>(_buffer + pos) = x;
@@ -291,14 +336,14 @@ struct BaseAssembler : public CodeGen {
return static_cast<size_t>(label.getId()) < _labels.getLength();
}
//! @internal
//! \internal
//!
//! Get `LabelData` by `label`.
ASMJIT_INLINE LabelData* getLabelData(const Label& label) const {
return getLabelDataById(label.getId());
}
//! @internal
//! \internal
//!
//! Get `LabelData` by `id`.
ASMJIT_INLINE LabelData* getLabelDataById(uint32_t id) const {
@@ -308,17 +353,17 @@ struct BaseAssembler : public CodeGen {
return const_cast<LabelData*>(&_labels[id]);
}
//! @internal
//! \internal
//!
//! Register labels for other code generator, i.e. `Compiler`.
ASMJIT_API Error _registerIndexedLabels(size_t index);
//! @internal
//! \internal
//!
//! Create and initialize a new `Label`.
ASMJIT_API Error _newLabel(Label* dst);
//! @internal
//! \internal
//!
//! New LabelLink instance.
ASMJIT_API LabelLink* _newLabelLink();
@@ -335,7 +380,7 @@ struct BaseAssembler : public CodeGen {
//! Bind label to the current offset.
//!
//! @note Label can be bound only once!
//! \note Label can be bound only once!
ASMJIT_INLINE void bind(const Label& label) {
_bind(label);
}
@@ -356,12 +401,14 @@ struct BaseAssembler : public CodeGen {
//! Typical usage of this is to align labels at start of the inner loops.
//!
//! Inserts `nop()` instructions or CPU optimized NOPs.
ASMJIT_INLINE Error align(uint32_t m) {
return _align(m);
ASMJIT_INLINE Error align(uint32_t mode, uint32_t offset) {
return _align(mode, offset);
}
//! Align target buffer to `m` bytes (virtual).
virtual Error _align(uint32_t m) = 0;
//! \internal
//!
//! Align target buffer to `m` bytes.
virtual Error _align(uint32_t mode, uint32_t offset) = 0;
// --------------------------------------------------------------------------
// [Reloc]
@@ -369,25 +416,25 @@ struct BaseAssembler : public CodeGen {
//! Simplifed version of `relocCode()` method designed for JIT.
//!
//! @overload
//! \overload
ASMJIT_INLINE size_t relocCode(void* dst) const {
return _relocCode(dst, static_cast<Ptr>((uintptr_t)dst));
}
//! Relocate code to a given address `dst`.
//!
//! @param dst Where the relocated code should me stored. The pointer can be
//! address returned by virtual memory allocator or your own address if you
//! want only to store the code for later reuse (or load, etc...).
//! @param addressBase Base address used for relocation. When using JIT code
//! generation, this will be the same as `dst`, only casted to system
//! integer type. But when generating code for remote process then the value
//! can be different.
//! \param dst Refers the location where the relocated code should be copied.
//! The pointer can be address returned by virtual memory allocator or any
//! custom address.
//!
//! @retval The bytes used. Code-generator can create trampolines which are
//! used when calling other functions inside the JIT code. However, these
//! trampolines can be unused so the relocCode() returns the exact size needed
//! for the function.
//! \param base Base address used for relocation. `JitRuntime` always sets
//! `base` address to be the same as `dst`, but other runtimes do not have
//! to follow this rule.
//!
//! \retval The number bytes used. If the code generator reserved space for
//! possible trampolines, but these weren't generated, the number of bytes
//! used can be actually less than the expected worst case. Virtual memory
//! allocator can in such case return some memory back to the pool.
//!
//! A given buffer will be overwritten, to get number of bytes required use
//! `getCodeSize()`.
@@ -395,7 +442,9 @@ struct BaseAssembler : public CodeGen {
return _relocCode(dst, base);
}
//! Reloc code (virtual).
//! \internal
//!
//! Reloc code.
virtual size_t _relocCode(void* dst, Ptr base) const = 0;
// --------------------------------------------------------------------------
@@ -410,24 +459,24 @@ struct BaseAssembler : public CodeGen {
//! Emit an instruction.
ASMJIT_API Error emit(uint32_t code);
//! @overload
//! \overload
ASMJIT_API Error emit(uint32_t code, const Operand& o0);
//! @overload
//! \overload
ASMJIT_API Error emit(uint32_t code, const Operand& o0, const Operand& o1);
//! @overload
//! \overload
ASMJIT_API Error emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2);
//! @overload
//! \overload
ASMJIT_INLINE Error emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2, const Operand& o3) {
return _emit(code, o0, o1, o2, o3);
}
//! Emit an instruction with integer immediate operand.
ASMJIT_API Error emit(uint32_t code, int o0);
//! @overload
//! \overload
ASMJIT_API Error emit(uint32_t code, const Operand& o0, int o1);
//! @overload
//! \overload
ASMJIT_API Error emit(uint32_t code, const Operand& o0, const Operand& o1, int o2);
//! @overload
//! \overload
ASMJIT_API Error emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2, int o3);
//! Emit an instruction (virtual).
@@ -464,7 +513,7 @@ struct BaseAssembler : public CodeGen {
PodVector<RelocData> _relocData;
};
//! @}
//! \}
// ============================================================================
// [Defined-Later]

View File

@@ -26,8 +26,8 @@ CodeGen::CodeGen(Runtime* runtime) :
_errorHandler(NULL),
_arch(kArchNone),
_regSize(0),
_features(static_cast<uint8_t>(IntUtil::mask(kCodeGenOptimizedAlign))),
_error(kErrorOk),
_features(IntUtil::mask(kCodeGenOptimizedAlign)),
_options(0),
_baseZone(16384 - sizeof(Zone::Chunk) - kMemAllocOverhead) {}

View File

@@ -9,7 +9,6 @@
#define _ASMJIT_BASE_CODEGEN_H
// [Dependencies - AsmJit]
#include "../base/defs.h"
#include "../base/error.h"
#include "../base/logger.h"
#include "../base/runtime.h"
@@ -20,16 +19,16 @@
namespace asmjit {
//! @addtogroup asmjit_base_codegen
//! @{
//! \addtogroup asmjit_base_general
//! \{
// ============================================================================
// [asmjit::kCodeGen]
// ============================================================================
//! Features of `CodeGen`.
//! Features of \ref CodeGen.
ASMJIT_ENUM(kCodeGen) {
//! Emit optimized code-alignment sequences.
//! Emit optimized code-alignment sequences (true by default).
//!
//! X86/X64
//! -------
@@ -41,11 +40,9 @@ ASMJIT_ENUM(kCodeGen) {
//! for alignment between 1 to 11 bytes. Also when `x86x64::Compiler` is
//! used, it may add rex prefixes into the code to make some instructions
//! greater so no alignment sequences are needed.
//!
//! Default true.
kCodeGenOptimizedAlign = 0,
//! Emit jump-prediction hints.
//! Emit jump-prediction hints (false by default).
//!
//! X86/X64
//! -------
@@ -57,15 +54,39 @@ ASMJIT_ENUM(kCodeGen) {
//! However this behavior can be overridden by using instruction prefixes.
//! If this option is enabled these hints will be emitted.
//!
//! Default true.
//! This feature is disabled by default, because the only processor that
//! used to take into consideration prediction hints was P4 that is not used
//! anymore.
kCodeGenPredictedJumps = 1
};
// ============================================================================
// [asmjit::kAlignMode]
// ============================================================================
//! Code aligning mode.
ASMJIT_ENUM(kAlignMode) {
kAlignCode = 0,
kAlignData = 1
};
// ============================================================================
// [asmjit::kRelocMode]
// ============================================================================
//! Relocation mode.
ASMJIT_ENUM(kRelocMode) {
kRelocAbsToAbs = 0,
kRelocRelToAbs = 1,
kRelocAbsToRel = 2,
kRelocTrampoline = 3
};
// ============================================================================
// [asmjit::CodeGen]
// ============================================================================
//! Abstract class inherited by `Assembler` and `Compiler`.
//! Abstract class defining basics of \ref Assembler and \ref BaseCompiler.
struct CodeGen {
ASMJIT_NO_COPY(CodeGen)
@@ -137,12 +158,17 @@ struct CodeGen {
// [Options]
// --------------------------------------------------------------------------
//! Get options.
ASMJIT_INLINE uint32_t getOptions() const { return _options; }
//! Set options.
ASMJIT_INLINE void setOptions(uint32_t options) { _options = options; }
//! Get options of the next instruction.
ASMJIT_INLINE uint32_t getOptions() const {
return _options;
}
//! Get options and clear them.
//! Set options of the next instruction.
ASMJIT_INLINE void setOptions(uint32_t options) {
_options = options;
}
//! Get options of the next instruction and clear them.
ASMJIT_INLINE uint32_t getOptionsAndClear() {
uint32_t options = _options;
_options = 0;
@@ -153,8 +179,8 @@ struct CodeGen {
// [Purge]
// --------------------------------------------------------------------------
//! Called by `clear()` and `reset()` to clear all data used by the code
//! generator.
//! Called by \ref clear() and \ref reset() to clear all data used by the
//! code generator.
virtual void _purge() = 0;
// --------------------------------------------------------------------------
@@ -177,17 +203,18 @@ struct CodeGen {
Runtime* _runtime;
//! Logger.
Logger* _logger;
//! Error handler, called by `setError()`.
//! Error handler, called by \ref setError().
ErrorHandler* _errorHandler;
//! Target architecture.
uint8_t _arch;
//! Get the default register size of the architecture (4 or 8 bytes).
//! Target general-purpose register size (4 or 8 bytes).
uint8_t _regSize;
//! Last error code.
uint8_t _error;
//! Target features.
uint8_t _features;
//! Last error code.
uint8_t _error;
//! Options for the next generated instruction (only 8-bits used).
uint32_t _options;
@@ -195,7 +222,7 @@ struct CodeGen {
Zone _baseZone;
};
//! @}
//! \}
} // asmjit namespace

View File

@@ -101,13 +101,13 @@ void BaseCompiler::_purge() {
// [asmjit::BaseCompiler - Node Management]
// ============================================================================
BaseNode* BaseCompiler::setCursor(BaseNode* node) {
BaseNode* old = _cursor;
Node* BaseCompiler::setCursor(Node* node) {
Node* old = _cursor;
_cursor = node;
return old;
}
BaseNode* BaseCompiler::addNode(BaseNode* node) {
Node* BaseCompiler::addNode(Node* node) {
ASMJIT_ASSERT(node != NULL);
ASMJIT_ASSERT(node->_prev == NULL);
ASMJIT_ASSERT(node->_next == NULL);
@@ -124,8 +124,8 @@ BaseNode* BaseCompiler::addNode(BaseNode* node) {
}
}
else {
BaseNode* prev = _cursor;
BaseNode* next = _cursor->_next;
Node* prev = _cursor;
Node* next = _cursor->_next;
node->_prev = prev;
node->_next = next;
@@ -141,14 +141,14 @@ BaseNode* BaseCompiler::addNode(BaseNode* node) {
return node;
}
BaseNode* BaseCompiler::addNodeBefore(BaseNode* node, BaseNode* ref) {
Node* BaseCompiler::addNodeBefore(Node* node, Node* ref) {
ASMJIT_ASSERT(node != NULL);
ASMJIT_ASSERT(node->_prev == NULL);
ASMJIT_ASSERT(node->_next == NULL);
ASMJIT_ASSERT(ref != NULL);
BaseNode* prev = ref->_prev;
BaseNode* next = ref;
Node* prev = ref->_prev;
Node* next = ref;
node->_prev = prev;
node->_next = next;
@@ -162,14 +162,14 @@ BaseNode* BaseCompiler::addNodeBefore(BaseNode* node, BaseNode* ref) {
return node;
}
BaseNode* BaseCompiler::addNodeAfter(BaseNode* node, BaseNode* ref) {
Node* BaseCompiler::addNodeAfter(Node* node, Node* ref) {
ASMJIT_ASSERT(node != NULL);
ASMJIT_ASSERT(node->_prev == NULL);
ASMJIT_ASSERT(node->_next == NULL);
ASMJIT_ASSERT(ref != NULL);
BaseNode* prev = ref;
BaseNode* next = ref->_next;
Node* prev = ref;
Node* next = ref->_next;
node->_prev = prev;
node->_next = next;
@@ -183,7 +183,7 @@ BaseNode* BaseCompiler::addNodeAfter(BaseNode* node, BaseNode* ref) {
return node;
}
static ASMJIT_INLINE void BaseCompiler_nodeRemoved(BaseCompiler* self, BaseNode* node_) {
static ASMJIT_INLINE void BaseCompiler_nodeRemoved(BaseCompiler* self, Node* node_) {
if (node_->isJmpOrJcc()) {
JumpNode* node = static_cast<JumpNode*>(node_);
TargetNode* target = node->getTarget();
@@ -209,9 +209,9 @@ static ASMJIT_INLINE void BaseCompiler_nodeRemoved(BaseCompiler* self, BaseNode*
}
}
BaseNode* BaseCompiler::removeNode(BaseNode* node) {
BaseNode* prev = node->_prev;
BaseNode* next = node->_next;
Node* BaseCompiler::removeNode(Node* node) {
Node* prev = node->_prev;
Node* next = node->_next;
if (_firstNode == node)
_firstNode = next;
@@ -233,14 +233,14 @@ BaseNode* BaseCompiler::removeNode(BaseNode* node) {
return node;
}
void BaseCompiler::removeNodes(BaseNode* first, BaseNode* last) {
void BaseCompiler::removeNodes(Node* first, Node* last) {
if (first == last) {
removeNode(first);
return;
}
BaseNode* prev = first->_prev;
BaseNode* next = last->_next;
Node* prev = first->_prev;
Node* next = last->_next;
if (_firstNode == first)
_firstNode = next;
@@ -252,9 +252,9 @@ void BaseCompiler::removeNodes(BaseNode* first, BaseNode* last) {
else
next->_prev = prev;
BaseNode* node = first;
Node* node = first;
for (;;) {
BaseNode* next = node->getNext();
Node* next = node->getNext();
ASMJIT_ASSERT(next != NULL);
node->_prev = NULL;
@@ -274,8 +274,8 @@ void BaseCompiler::removeNodes(BaseNode* first, BaseNode* last) {
// [asmjit::BaseCompiler - Align]
// ============================================================================
AlignNode* BaseCompiler::newAlign(uint32_t m) {
AlignNode* node = newNode<AlignNode>(m);
AlignNode* BaseCompiler::newAlign(uint32_t mode, uint32_t offset) {
AlignNode* node = newNode<AlignNode>(mode, offset);
if (node == NULL)
goto _NoMemory;
return node;
@@ -285,8 +285,8 @@ _NoMemory:
return NULL;
}
AlignNode* BaseCompiler::addAlign(uint32_t m) {
AlignNode* node = newAlign(m);
AlignNode* BaseCompiler::addAlign(uint32_t mode, uint32_t offset) {
AlignNode* node = newAlign(mode, offset);
if (node == NULL)
return NULL;
return static_cast<AlignNode*>(addNode(node));

View File

@@ -12,10 +12,10 @@
#include "../base/assembler.h"
#include "../base/codegen.h"
#include "../base/constpool.h"
#include "../base/defs.h"
#include "../base/error.h"
#include "../base/func.h"
#include "../base/intutil.h"
#include "../base/operand.h"
#include "../base/podlist.h"
#include "../base/podvector.h"
#include "../base/runtime.h"
@@ -26,9 +26,6 @@
namespace asmjit {
//! @addtogroup asmjit_base_codegen
//! @{
// ============================================================================
// [Forward Declarations]
// ============================================================================
@@ -40,7 +37,7 @@ struct VarData;
struct BaseVarInst;
struct BaseVarState;
struct BaseNode;
struct Node;
struct EndNode;
struct InstNode;
struct JumpNode;
@@ -49,6 +46,9 @@ struct JumpNode;
// [asmjit::kConstScope]
// ============================================================================
//! \addtogroup asmjit_base_general
//! \{
//! Scope of the constant.
ASMJIT_ENUM(kConstScope) {
//! Local constant, always embedded right after the current function.
@@ -57,10 +57,15 @@ ASMJIT_ENUM(kConstScope) {
kConstScopeGlobal = 1
};
//! \}
// ============================================================================
// [asmjit::kVarAttrFlags]
// ============================================================================
//! \addtogroup asmjit_base_tree
//! \{
//! Variable attribute flags.
ASMJIT_ENUM(kVarAttrFlags) {
//! Variable is accessed through register on input.
@@ -101,6 +106,9 @@ ASMJIT_ENUM(kVarAttrFlags) {
//! Variable should be unused at the end of the instruction/node.
kVarAttrUnuse = 0x00000800,
//! \internal
//!
//! All in-flags.
kVarAttrInAll =
kVarAttrInReg |
kVarAttrInMem |
@@ -108,6 +116,9 @@ ASMJIT_ENUM(kVarAttrFlags) {
kVarAttrInCall |
kVarAttrInArg,
//! \internal
//!
//! All out-flags.
kVarAttrOutAll =
kVarAttrOutReg |
kVarAttrOutMem |
@@ -146,7 +157,7 @@ ASMJIT_ENUM(kVarHint) {
//! State of variable.
//!
//! @note State of variable is used only during make process and it's not
//! \note State of variable is used only during make process and it's not
//! visible to the developer.
ASMJIT_ENUM(kVarState) {
//! Variable is currently not used.
@@ -168,31 +179,31 @@ ASMJIT_ENUM(kVarState) {
// [asmjit::kNodeType]
// ============================================================================
//! Type of node (see `BaseNode)`.
//! Type of node, see \ref Node.
ASMJIT_ENUM(kNodeType) {
//! Invalid node (internal, can't be used).
kNodeTypeNone = 0,
//! Node is an .align directive, see `AlignNode`.
//! Node is an .align directive, see \ref AlignNode.
kNodeTypeAlign,
//! Node is an embedded data, see `EmbedNode`.
//! Node is an embedded data, see \ref EmbedNode.
kNodeTypeEmbed,
//! Node is a comment, see `CommentNode`.
//! Node is a comment, see \ref CommentNode.
kNodeTypeComment,
//! Node is a variable hint (alloc, spill, use, unuse), see `HintNode`.
//! Node is a variable hint (alloc, spill, use, unuse), see \ref HintNode.
kNodeTypeHint,
//! Node is a label, see `TargetNode`.
//! Node is a label, see \ref TargetNode.
kNodeTypeTarget,
//! Node is an instruction, see `InstNode`.
//! Node is an instruction, see \ref InstNode.
kNodeTypeInst,
//! Node is a function declaration, see `FuncNode`.
//! Node is a function declaration, see \ref FuncNode.
kNodeTypeFunc,
//! Node is an end of the function, see `EndNode`.
//! Node is an end of the function, see \ref EndNode.
kNodeTypeEnd,
//! Node is a return, see `RetNode`.
//! Node is a return, see \ref RetNode.
kNodeTypeRet,
//! Node is a function call, see `CallNode`.
//! Node is a function call, see \ref CallNode.
kNodeTypeCall,
//! Node is a function call argument moved on stack, see `SArgNode`.
//! Node is a function call argument moved on stack, see \ref SArgNode.
kNodeTypeSArg
};
@@ -225,10 +236,15 @@ ASMJIT_ENUM(kNodeFlag) {
kNodeFlagIsFp = 0x0040
};
//! \}
// ============================================================================
// [asmjit::MemCell]
// ============================================================================
//! \addtogroup asmjit_base_tree
//! \{
struct MemCell {
ASMJIT_NO_COPY(MemCell)
@@ -507,7 +523,7 @@ struct VarData {
uint8_t _saveOnUnuse : 1;
//! Whether variable was changed (connected with actual `BaseVarState)`.
uint8_t _modified : 1;
//! @internal
//! \internal
uint8_t _reserved0 : 3;
//! Variable natural alignment.
uint8_t _alignment;
@@ -547,7 +563,9 @@ struct VarData {
//! back to zero/null. Initial value is NULL.
VarAttr* _va;
//! @internal
//! \internal
//!
//! Same as `_va` just provided as `uintptr_t`.
uintptr_t _vaUInt;
};
};
@@ -677,11 +695,11 @@ struct VarAttr {
//!
//! Typically `kInvalidReg` if variable is only used on input.
uint8_t _outRegIndex;
//! @internal
//! \internal
uint8_t _reserved;
};
//! @internal
//! \internal
//!
//! Packed data #0.
uint32_t _packed;
@@ -721,36 +739,36 @@ struct BaseVarInst {};
struct BaseVarState {};
// ============================================================================
// [asmjit::BaseNode]
// [asmjit::Node]
// ============================================================================
//! Base node.
//!
//! `Every` node represents an abstract instruction, directive, label, or
//! macro-instruction generated by compiler.
struct BaseNode {
ASMJIT_NO_COPY(BaseNode)
struct Node {
ASMJIT_NO_COPY(Node)
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! Create new `BaseNode`.
//! Create new `Node`.
//!
//! @note Always use compiler to create nodes.
ASMJIT_INLINE BaseNode(BaseCompiler* compiler, uint32_t type); // Defined-Later.
//! \note Always use compiler to create nodes.
ASMJIT_INLINE Node(BaseCompiler* compiler, uint32_t type); // Defined-Later.
//! Destroy `BaseNode`.
ASMJIT_INLINE ~BaseNode() {}
//! Destroy `Node`.
ASMJIT_INLINE ~Node() {}
// --------------------------------------------------------------------------
// [Accessors]
// --------------------------------------------------------------------------
//! Get previous node in the compiler stream.
ASMJIT_INLINE BaseNode* getPrev() const { return _prev; }
ASMJIT_INLINE Node* getPrev() const { return _prev; }
//! Get next node in the compiler stream.
ASMJIT_INLINE BaseNode* getNext() const { return _next; }
ASMJIT_INLINE Node* getNext() const { return _next; }
//! Get comment string.
ASMJIT_INLINE const char* getComment() const { return _comment; }
@@ -827,9 +845,9 @@ struct BaseNode {
// --------------------------------------------------------------------------
//! Previous node.
BaseNode* _prev;
Node* _prev;
//! Next node.
BaseNode* _next;
Node* _next;
//! Node type, see `kNodeType`.
uint8_t _type;
@@ -863,7 +881,7 @@ struct BaseNode {
// ============================================================================
//! Align node.
struct AlignNode : public BaseNode {
struct AlignNode : public Node {
ASMJIT_NO_COPY(AlignNode)
// --------------------------------------------------------------------------
@@ -871,8 +889,11 @@ struct AlignNode : public BaseNode {
// --------------------------------------------------------------------------
//! Create a new `AlignNode` instance.
ASMJIT_INLINE AlignNode(BaseCompiler* compiler, uint32_t size) : BaseNode(compiler, kNodeTypeAlign) {
_size = size;
ASMJIT_INLINE AlignNode(BaseCompiler* compiler, uint32_t mode, uint32_t offset) :
Node(compiler, kNodeTypeAlign) {
_mode = mode;
_offset = offset;
}
//! Destroy the `AlignNode` instance.
@@ -882,17 +903,34 @@ struct AlignNode : public BaseNode {
// [Accessors]
// --------------------------------------------------------------------------
//! Get align size in bytes.
ASMJIT_INLINE uint32_t getSize() const { return _size; }
//! Set align size in bytes to `size`.
ASMJIT_INLINE void setSize(uint32_t size) { _size = size; }
//! Get alignment mode.
ASMJIT_INLINE uint32_t getMode() const {
return _mode;
}
//! Set alignment mode.
ASMJIT_INLINE void setMode(uint32_t mode) {
_mode = mode;
}
//! Get align offset in bytes.
ASMJIT_INLINE uint32_t getOffset() const {
return _offset;
}
//! Set align offset in bytes to `offset`.
ASMJIT_INLINE void setOffset(uint32_t offset) {
_offset = offset;
}
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
//! Size of the alignment.
uint32_t _size;
//! Alignment mode, see \ref kAlignMode.
uint32_t _mode;
//! Alignment offset in bytes.
uint32_t _offset;
};
// ============================================================================
@@ -903,7 +941,7 @@ struct AlignNode : public BaseNode {
//!
//! Embed node is used to embed data into final assembler stream. The data is
//! considered to be RAW; No analysis is performed on RAW data.
struct EmbedNode : public BaseNode {
struct EmbedNode : public Node {
ASMJIT_NO_COPY(EmbedNode)
// --------------------------------------------------------------------------
@@ -917,7 +955,7 @@ struct EmbedNode : public BaseNode {
// --------------------------------------------------------------------------
//! Create a new `EmbedNode` instance.
ASMJIT_INLINE EmbedNode(BaseCompiler* compiler, void* data, uint32_t size) : BaseNode(compiler, kNodeTypeEmbed) {
ASMJIT_INLINE EmbedNode(BaseCompiler* compiler, void* data, uint32_t size) : Node(compiler, kNodeTypeEmbed) {
_size = size;
if (size <= kInlineBufferSize) {
if (data != NULL)
@@ -964,7 +1002,7 @@ struct EmbedNode : public BaseNode {
//! Comments allows to comment your assembler stream for better debugging
//! and visualization. Comments are usually ignored in release builds unless
//! the logger is present.
struct CommentNode : public BaseNode {
struct CommentNode : public Node {
ASMJIT_NO_COPY(CommentNode)
// --------------------------------------------------------------------------
@@ -972,7 +1010,7 @@ struct CommentNode : public BaseNode {
// --------------------------------------------------------------------------
//! Create a new `CommentNode` instance.
ASMJIT_INLINE CommentNode(BaseCompiler* compiler, const char* comment) : BaseNode(compiler, kNodeTypeComment) {
ASMJIT_INLINE CommentNode(BaseCompiler* compiler, const char* comment) : Node(compiler, kNodeTypeComment) {
_comment = comment;
}
@@ -985,7 +1023,7 @@ struct CommentNode : public BaseNode {
// ============================================================================
//! Hint node.
struct HintNode : public BaseNode {
struct HintNode : public Node {
ASMJIT_NO_COPY(HintNode)
// --------------------------------------------------------------------------
@@ -993,7 +1031,7 @@ struct HintNode : public BaseNode {
// --------------------------------------------------------------------------
//! Create a new `HintNode` instance.
ASMJIT_INLINE HintNode(BaseCompiler* compiler, VarData* vd, uint32_t hint, uint32_t value) : BaseNode(compiler, kNodeTypeHint) {
ASMJIT_INLINE HintNode(BaseCompiler* compiler, VarData* vd, uint32_t hint, uint32_t value) : Node(compiler, kNodeTypeHint) {
_vd = vd;
_hint = hint;
_value = value;
@@ -1036,7 +1074,7 @@ struct HintNode : public BaseNode {
// ============================================================================
//! label node.
struct TargetNode : public BaseNode {
struct TargetNode : public Node {
ASMJIT_NO_COPY(TargetNode)
// --------------------------------------------------------------------------
@@ -1044,7 +1082,7 @@ struct TargetNode : public BaseNode {
// --------------------------------------------------------------------------
//! Create a new `TargetNode` instance.
ASMJIT_INLINE TargetNode(BaseCompiler* compiler, uint32_t labelId) : BaseNode(compiler, kNodeTypeTarget) {
ASMJIT_INLINE TargetNode(BaseCompiler* compiler, uint32_t labelId) : Node(compiler, kNodeTypeTarget) {
_id = labelId;
_numRefs = 0;
_from = NULL;
@@ -1100,7 +1138,7 @@ struct TargetNode : public BaseNode {
// ============================================================================
//! Instruction node.
struct InstNode : public BaseNode {
struct InstNode : public Node {
ASMJIT_NO_COPY(InstNode)
// --------------------------------------------------------------------------
@@ -1108,7 +1146,7 @@ struct InstNode : public BaseNode {
// --------------------------------------------------------------------------
//! Create a new `InstNode` instance.
ASMJIT_INLINE InstNode(BaseCompiler* compiler, uint32_t code, uint32_t options, Operand* opList, uint32_t opCount) : BaseNode(compiler, kNodeTypeInst) {
ASMJIT_INLINE InstNode(BaseCompiler* compiler, uint32_t code, uint32_t options, Operand* opList, uint32_t opCount) : Node(compiler, kNodeTypeInst) {
_code = static_cast<uint16_t>(code);
_options = static_cast<uint8_t>(options);
@@ -1170,7 +1208,7 @@ struct InstNode : public BaseNode {
ASMJIT_INLINE Operand* getOpList() {
return _opList;
}
//! @overload
//! \overload
ASMJIT_INLINE const Operand* getOpList() const {
return _opList;
}
@@ -1203,7 +1241,7 @@ struct InstNode : public BaseNode {
return static_cast<BaseMem*>(&_opList[_memOpIndex]);
}
//! @overload
//! \overload
template<typename T>
ASMJIT_INLINE T* getMemOp() const {
ASMJIT_ASSERT(hasMemOp());
@@ -1236,7 +1274,7 @@ _Update:
uint16_t _code;
//! Instruction options, see `kInstOptions`.
uint8_t _options;
//! @internal
//! \internal
uint8_t _memOpIndex;
//! Operands list.
@@ -1289,7 +1327,7 @@ struct JumpNode : public InstNode {
//! `FuncNode` can be used to generate function prolog and epilog which are
//! compatible with a given function calling convention and to allocate and
//! manage variables that can be allocated/spilled during compilation phase.
struct FuncNode : public BaseNode {
struct FuncNode : public Node {
ASMJIT_NO_COPY(FuncNode)
// --------------------------------------------------------------------------
@@ -1300,7 +1338,7 @@ struct FuncNode : public BaseNode {
//!
//! Always use `BaseCompiler::addFunc()` to create a `FuncNode` instance.
ASMJIT_INLINE FuncNode(BaseCompiler* compiler) :
BaseNode(compiler, kNodeTypeFunc),
Node(compiler, kNodeTypeFunc),
_entryNode(NULL),
_exitNode(NULL),
_decl(NULL),
@@ -1472,7 +1510,7 @@ struct FuncNode : public BaseNode {
//! Expected stack alignment (we depend on this value).
//!
//! @note It can be global alignment given by the OS or described by an
//! \note It can be global alignment given by the OS or described by an
//! target platform ABI.
uint32_t _expectedStackAlignment;
//! Required stack alignment (usually for multimedia instructions).
@@ -1498,7 +1536,7 @@ struct FuncNode : public BaseNode {
// ============================================================================
//! End of function/block node.
struct EndNode : public BaseNode {
struct EndNode : public Node {
ASMJIT_NO_COPY(EndNode)
// --------------------------------------------------------------------------
@@ -1506,7 +1544,7 @@ struct EndNode : public BaseNode {
// --------------------------------------------------------------------------
//! Create a new `EndNode` instance.
ASMJIT_INLINE EndNode(BaseCompiler* compiler) : BaseNode(compiler, kNodeTypeEnd) {
ASMJIT_INLINE EndNode(BaseCompiler* compiler) : Node(compiler, kNodeTypeEnd) {
_flags |= kNodeFlagIsRet;
}
@@ -1519,7 +1557,7 @@ struct EndNode : public BaseNode {
// ============================================================================
//! Function return node.
struct RetNode : public BaseNode {
struct RetNode : public Node {
ASMJIT_NO_COPY(RetNode)
// --------------------------------------------------------------------------
@@ -1527,7 +1565,7 @@ struct RetNode : public BaseNode {
// --------------------------------------------------------------------------
//! Create a new `RetNode` instance.
ASMJIT_INLINE RetNode(BaseCompiler* compiler, const Operand& o0, const Operand& o1) : BaseNode(compiler, kNodeTypeRet) {
ASMJIT_INLINE RetNode(BaseCompiler* compiler, const Operand& o0, const Operand& o1) : Node(compiler, kNodeTypeRet) {
_flags |= kNodeFlagIsRet;
_ret[0] = o0;
_ret[1] = o1;
@@ -1542,12 +1580,12 @@ struct RetNode : public BaseNode {
//! Get the first return operand.
ASMJIT_INLINE Operand& getFirst() { return _ret[0]; }
//! @overload
//! \overload
ASMJIT_INLINE const Operand& getFirst() const { return _ret[0]; }
//! Get the second return operand.
ASMJIT_INLINE Operand& getSecond() { return _ret[1]; }
//! @overload
//! \overload
ASMJIT_INLINE const Operand& getSecond() const { return _ret[1]; }
// --------------------------------------------------------------------------
@@ -1563,7 +1601,7 @@ struct RetNode : public BaseNode {
// ============================================================================
//! Function-call node.
struct CallNode : public BaseNode {
struct CallNode : public Node {
ASMJIT_NO_COPY(CallNode)
// --------------------------------------------------------------------------
@@ -1572,7 +1610,7 @@ struct CallNode : public BaseNode {
//! Create a new `CallNode` instance.
ASMJIT_INLINE CallNode(BaseCompiler* compiler, const Operand& target) :
BaseNode(compiler, kNodeTypeCall),
Node(compiler, kNodeTypeCall),
_decl(NULL),
_target(target),
_args(NULL) {}
@@ -1589,7 +1627,7 @@ struct CallNode : public BaseNode {
//! Get target operand.
ASMJIT_INLINE Operand& getTarget() { return _target; }
//! @overload
//! \overload
ASMJIT_INLINE const Operand& getTarget() const { return _target; }
//! Get return at `i`.
@@ -1597,7 +1635,7 @@ struct CallNode : public BaseNode {
ASMJIT_ASSERT(i < 2);
return _ret[i];
}
//! @overload
//! \overload
ASMJIT_INLINE const Operand& getRet(uint32_t i = 0) const {
ASMJIT_ASSERT(i < 2);
return _ret[i];
@@ -1608,7 +1646,7 @@ struct CallNode : public BaseNode {
ASMJIT_ASSERT(i < kFuncArgCountLoHi);
return _args[i];
}
//! @overload
//! \overload
ASMJIT_INLINE const Operand& getArg(uint32_t i) const {
ASMJIT_ASSERT(i < kFuncArgCountLoHi);
return _args[i];
@@ -1634,7 +1672,7 @@ struct CallNode : public BaseNode {
// ============================================================================
//! Function-call 'argument on the stack' node.
struct SArgNode : public BaseNode {
struct SArgNode : public Node {
ASMJIT_NO_COPY(SArgNode)
// --------------------------------------------------------------------------
@@ -1643,7 +1681,7 @@ struct SArgNode : public BaseNode {
//! Create a new `SArgNode` instance.
ASMJIT_INLINE SArgNode(BaseCompiler* compiler, CallNode* call, VarData* sVd, VarData* cVd) :
BaseNode(compiler, kNodeTypeSArg),
Node(compiler, kNodeTypeSArg),
_call(call),
_sVd(sVd),
_cVd(cVd),
@@ -1678,10 +1716,15 @@ struct SArgNode : public BaseNode {
uint32_t _args;
};
//! \}
// ============================================================================
// [asmjit::BaseCompiler]
// ============================================================================
//! \addtogroup asmjit_base_general
//! \{
//! Base compiler.
//!
//! @sa BaseAssembler.
@@ -1712,11 +1755,11 @@ struct BaseCompiler : public CodeGen {
//! Clear everything, but keep buffers allocated.
//!
//! @note This method will destroy your code.
//! \note This method will destroy your code.
ASMJIT_API void clear();
//! Clear everything and reset all buffers.
//!
//! @note This method will destroy your code.
//! \note This method will destroy your code.
ASMJIT_API void reset();
//! Called by clear() and reset() to clear all data related to derived
//! class implementation.
@@ -1751,30 +1794,30 @@ struct BaseCompiler : public CodeGen {
}
//! Get first node.
ASMJIT_INLINE BaseNode* getFirstNode() const { return _firstNode; }
ASMJIT_INLINE Node* getFirstNode() const { return _firstNode; }
//! Get last node.
ASMJIT_INLINE BaseNode* getLastNode() const { return _lastNode; }
ASMJIT_INLINE Node* getLastNode() const { return _lastNode; }
//! Get current node.
//!
//! @note If this method returns `NULL` it means that nothing has been emitted
//! \note If this method returns `NULL` it means that nothing has been emitted
//! yet.
ASMJIT_INLINE BaseNode* getCursor() const { return _cursor; }
ASMJIT_INLINE Node* getCursor() const { return _cursor; }
//! Set the current node without returning the previous node (private).
ASMJIT_INLINE void _setCursor(BaseNode* node) { _cursor = node; }
ASMJIT_INLINE void _setCursor(Node* node) { _cursor = node; }
//! Set the current node to `node` and return the previous one.
ASMJIT_API BaseNode* setCursor(BaseNode* node);
ASMJIT_API Node* setCursor(Node* node);
//! Add node `node` after current and set current to `node`.
ASMJIT_API BaseNode* addNode(BaseNode* node);
ASMJIT_API Node* addNode(Node* node);
//! Add node before `ref`.
ASMJIT_API BaseNode* addNodeBefore(BaseNode* node, BaseNode* ref);
ASMJIT_API Node* addNodeBefore(Node* node, Node* ref);
//! Add node after `ref`.
ASMJIT_API BaseNode* addNodeAfter(BaseNode* node, BaseNode* ref);
ASMJIT_API Node* addNodeAfter(Node* node, Node* ref);
//! Remove node `node`.
ASMJIT_API BaseNode* removeNode(BaseNode* node);
ASMJIT_API Node* removeNode(Node* node);
//! Remove multiple nodes.
ASMJIT_API void removeNodes(BaseNode* first, BaseNode* last);
ASMJIT_API void removeNodes(Node* first, Node* last);
// --------------------------------------------------------------------------
// [Func]
@@ -1788,16 +1831,18 @@ struct BaseCompiler : public CodeGen {
// --------------------------------------------------------------------------
//! Create a new `AlignNode`.
ASMJIT_API AlignNode* newAlign(uint32_t m);
ASMJIT_API AlignNode* newAlign(uint32_t mode, uint32_t offset);
//! Add a new `AlignNode`.
ASMJIT_API AlignNode* addAlign(uint32_t m);
ASMJIT_API AlignNode* addAlign(uint32_t mode, uint32_t offset);
//! Align target buffer to `m` bytes.
//!
//! Typical usage of this is to align labels at start of the inner loops.
//!
//! Inserts `nop()` instructions or CPU optimized NOPs.
ASMJIT_INLINE AlignNode* align(uint32_t m) { return addAlign(m); }
ASMJIT_INLINE AlignNode* align(uint32_t mode, uint32_t offset) {
return addAlign(mode, offset);
}
// --------------------------------------------------------------------------
// [Target]
@@ -1826,14 +1871,16 @@ struct BaseCompiler : public CodeGen {
// --------------------------------------------------------------------------
//! Get count of created labels.
ASMJIT_INLINE size_t getLabelsCount() const
{ return _targets.getLength(); }
ASMJIT_INLINE size_t getLabelsCount() const {
return _targets.getLength();
}
//! Get whether `label` is created.
ASMJIT_INLINE bool isLabelCreated(const Label& label) const
{ return static_cast<size_t>(label.getId()) < _targets.getLength(); }
ASMJIT_INLINE bool isLabelCreated(const Label& label) const {
return static_cast<size_t>(label.getId()) < _targets.getLength();
}
//! @internal
//! \internal
//!
//! Create and initialize a new `Label`.
ASMJIT_API Error _newLabel(Label* dst);
@@ -1847,7 +1894,7 @@ struct BaseCompiler : public CodeGen {
//! Bind label to the current offset.
//!
//! @note Label can be bound only once!
//! \note Label can be bound only once!
ASMJIT_API void bind(const Label& label);
// --------------------------------------------------------------------------
@@ -1860,7 +1907,9 @@ struct BaseCompiler : public CodeGen {
ASMJIT_API EmbedNode* addEmbed(const void* data, uint32_t size);
//! Embed data.
ASMJIT_INLINE EmbedNode* embed(const void* data, uint32_t size) { return addEmbed(data, size); }
ASMJIT_INLINE EmbedNode* embed(const void* data, uint32_t size) {
return addEmbed(data, size);
}
// --------------------------------------------------------------------------
// [Comment]
@@ -1892,14 +1941,14 @@ struct BaseCompiler : public CodeGen {
return static_cast<size_t>(var.getId() & kOperandIdNum) < _vars.getLength();
}
//! @internal
//! \internal
//!
//! Get `VarData` by `var`.
ASMJIT_INLINE VarData* getVd(const BaseVar& var) const {
return getVdById(var.getId());
}
//! @internal
//! \internal
//!
//! Get `VarData` by `id`.
ASMJIT_INLINE VarData* getVdById(uint32_t id) const {
@@ -1909,14 +1958,14 @@ struct BaseCompiler : public CodeGen {
return _vars[id & kOperandIdNum];
}
//! @internal
//! \internal
//!
//! Get an array of 'VarData*'.
ASMJIT_INLINE VarData** _getVdArray() const {
return const_cast<VarData**>(_vars.getData());
}
//! @internal
//! \internal
//!
//! Create a new `VarData`.
ASMJIT_API VarData* _newVd(uint32_t type, uint32_t size, uint32_t c, const char* name);
@@ -1949,14 +1998,14 @@ struct BaseCompiler : public CodeGen {
//! Rename variable `var` to `name`.
//!
//! @note Only new name will appear in the logger.
//! \note Only new name will appear in the logger.
ASMJIT_API void rename(BaseVar& var, const char* name);
// --------------------------------------------------------------------------
// [Stack]
// --------------------------------------------------------------------------
//! @internal
//! \internal
//!
//! Create a new memory chunk allocated on the current function's stack.
virtual Error _newStack(BaseMem* mem, uint32_t size, uint32_t alignment, const char* name) = 0;
@@ -1965,7 +2014,7 @@ struct BaseCompiler : public CodeGen {
// [Const]
// --------------------------------------------------------------------------
//! @internal
//! \internal
//!
//! Put data to a constant-pool and get a memory reference to it.
virtual Error _newConst(BaseMem* mem, uint32_t scope, const void* data, size_t size) = 0;
@@ -1993,12 +2042,12 @@ struct BaseCompiler : public CodeGen {
const uint8_t* _targetVarMapping;
//! First node.
BaseNode* _firstNode;
Node* _firstNode;
//! Last node.
BaseNode* _lastNode;
Node* _lastNode;
//! Current node.
BaseNode* _cursor;
Node* _cursor;
//! Current function.
FuncNode* _func;
@@ -2025,6 +2074,8 @@ struct BaseCompiler : public CodeGen {
Label _globalConstPoolLabel;
};
//! \}
// ============================================================================
// [Defined-Later]
// ============================================================================
@@ -2033,7 +2084,7 @@ ASMJIT_INLINE Label::Label(BaseCompiler& c) : Operand(NoInit) {
c._newLabel(this);
}
ASMJIT_INLINE BaseNode::BaseNode(BaseCompiler* compiler, uint32_t type) {
ASMJIT_INLINE Node::Node(BaseCompiler* compiler, uint32_t type) {
_prev = NULL;
_next = NULL;
_type = static_cast<uint8_t>(type);
@@ -2046,8 +2097,6 @@ ASMJIT_INLINE BaseNode::BaseNode(BaseCompiler* compiler, uint32_t type) {
_state = NULL;
}
//! @}
} // asmjit namespace
// [Api-End]

View File

@@ -29,7 +29,7 @@ const ConstPoolNode ConstPoolTree::_sentinel = { {
const_cast<ConstPoolNode*>(&ConstPoolTree::_sentinel)
}, 0, 0, 0 };
//! @internal
//! \internal
//!
//! Remove left horizontal links.
static ASMJIT_INLINE ConstPoolNode* ConstPoolTree_skewNode(ConstPoolNode* node) {
@@ -43,7 +43,7 @@ static ASMJIT_INLINE ConstPoolNode* ConstPoolTree_skewNode(ConstPoolNode* node)
return node;
}
//! @internal
//! \internal
//!
//! Remove consecutive horizontal links.
static ASMJIT_INLINE ConstPoolNode* ConstPoolTree_splitNode(ConstPoolNode* node) {

View File

@@ -17,14 +17,14 @@
namespace asmjit {
//! @addtogroup asmjit_base_util
//! @{
//! \addtogroup asmjit_base_util
//! \{
// ============================================================================
// [asmjit::ConstPoolNode]
// ============================================================================
//! @internal
//! \internal
//!
//! Zone-allocated constant-pool node.
struct ConstPoolNode {
@@ -54,7 +54,7 @@ struct ConstPoolNode {
// [asmjit::ConstPoolTree]
// ============================================================================
//! @internal
//! \internal
//!
//! Zone-allocated constant-pool tree.
struct ConstPoolTree {
@@ -184,7 +184,7 @@ struct ConstPoolTree {
// [asmjit::ConstPoolGap]
// ============================================================================
//! @internal
//! \internal
//!
//! Zone-allocated constant-pool gap.
struct ConstPoolGap {
@@ -291,7 +291,7 @@ struct ConstPool {
size_t _alignment;
};
//! @}
//! \}
} // asmjit namespace

View File

@@ -265,14 +265,14 @@ Error BaseContext::resolveCellOffsets() {
// ============================================================================
Error BaseContext::removeUnreachableCode() {
PodList<BaseNode*>::Link* link = _unreachableList.getFirst();
BaseNode* stop = getStop();
PodList<Node*>::Link* link = _unreachableList.getFirst();
Node* stop = getStop();
while (link != NULL) {
BaseNode* node = link->getValue();
Node* node = link->getValue();
if (node != NULL && node->getPrev() != NULL) {
// Locate all unreachable nodes.
BaseNode* first = node;
Node* first = node;
do {
if (node->isFetched())
break;
@@ -281,7 +281,7 @@ Error BaseContext::removeUnreachableCode() {
// Remove.
if (node != first) {
BaseNode* last = (node != NULL) ? node->getPrev() : getCompiler()->getLastNode();
Node* last = (node != NULL) ? node->getPrev() : getCompiler()->getLastNode();
getCompiler()->removeNodes(first, last);
}
}
@@ -296,7 +296,7 @@ Error BaseContext::removeUnreachableCode() {
// [asmjit::BaseContext - Cleanup]
// ============================================================================
//! @internal
//! \internal
//!
//! Translate the given function `func`.
void BaseContext::cleanup() {
@@ -318,8 +318,8 @@ void BaseContext::cleanup() {
// ============================================================================
Error BaseContext::compile(FuncNode* func) {
BaseNode* end = func->getEnd();
BaseNode* stop = end->getNext();
Node* end = func->getEnd();
Node* stop = end->getNext();
_func = func;
_stop = stop;

View File

@@ -17,14 +17,14 @@
namespace asmjit {
//! @addtogroup asmjit_base_codegen
//! @{
//! \addtogroup asmjit_base_tree
//! \{
// ============================================================================
// [asmjit::BaseContext]
// ============================================================================
//! @internal
//! \internal
//!
//! Code generation context is the logic behind `BaseCompiler`. The context is
//! used to compile the code stored in `BaseCompiler`.
@@ -55,17 +55,17 @@ struct BaseContext {
//! Get function.
ASMJIT_INLINE FuncNode* getFunc() const { return _func; }
//! Get stop node.
ASMJIT_INLINE BaseNode* getStop() const { return _stop; }
ASMJIT_INLINE Node* getStop() const { return _stop; }
//! Get start of the current scope.
ASMJIT_INLINE BaseNode* getStart() const { return _start; }
ASMJIT_INLINE Node* getStart() const { return _start; }
//! Get end of the current scope.
ASMJIT_INLINE BaseNode* getEnd() const { return _end; }
ASMJIT_INLINE Node* getEnd() const { return _end; }
//! Get extra block.
ASMJIT_INLINE BaseNode* getExtraBlock() const { return _extraBlock; }
ASMJIT_INLINE Node* getExtraBlock() const { return _extraBlock; }
//! Set extra block.
ASMJIT_INLINE void setExtraBlock(BaseNode* node) { _extraBlock = node; }
ASMJIT_INLINE void setExtraBlock(Node* node) { _extraBlock = node; }
// --------------------------------------------------------------------------
// [Error]
@@ -207,7 +207,7 @@ struct BaseContext {
// [Serialize]
// --------------------------------------------------------------------------
virtual Error serialize(BaseAssembler* assembler, BaseNode* start, BaseNode* stop) = 0;
virtual Error serialize(BaseAssembler* assembler, Node* start, Node* stop) = 0;
// --------------------------------------------------------------------------
// [Members]
@@ -222,19 +222,19 @@ struct BaseContext {
Zone _baseZone;
//! Start of the current active scope.
BaseNode* _start;
Node* _start;
//! End of the current active scope.
BaseNode* _end;
Node* _end;
//! Node that is used to insert extra code after the function body.
BaseNode* _extraBlock;
Node* _extraBlock;
//! Stop node.
BaseNode* _stop;
Node* _stop;
//! Unreachable nodes.
PodList<BaseNode*> _unreachableList;
PodList<Node*> _unreachableList;
//! Jump nodes.
PodList<BaseNode*> _jccList;
PodList<Node*> _jccList;
//! All variables used by the current function.
PodVector<VarData*> _contextVd;
@@ -277,7 +277,7 @@ struct BaseContext {
BaseVarState* _state;
};
//! @}
//! \}
} // asmjit namespace

View File

@@ -16,11 +16,6 @@
// ?
#endif // ASMJIT_HOST || ASMJIT_HOST_X64
// [Dependencies - Windows]
#if defined(ASMJIT_OS_WINDOWS)
# include <windows.h>
#endif // ASMJIT_OS_WINDOWS
// [Dependencies - Posix]
#if defined(ASMJIT_OS_POSIX)
# include <errno.h>

View File

@@ -16,31 +16,30 @@
namespace asmjit {
//! @addtogroup asmjit_base_cpu_info
//! @{
//! \addtogroup asmjit_base_general
//! \{
// ============================================================================
// [asmjit::kCpuVendor]
// ============================================================================
//! Cpu vendor IDs.
//! Cpu vendor ID.
//!
//! Cpu vendor IDs are specific for AsmJit library. Vendor ID is not directly
//! read from cpuid result, instead it's based on CPU vendor string.
//! Vendor IDs are specific to AsmJit library. During the library initialization
//! AsmJit checks host CPU and tries to identify the vendor based on the CPUID
//! calls. Some manufacturers changed their vendor strings and AsmJit is aware
//! of that - it checks multiple combinations and decides which vendor ID should
//! be used.
ASMJIT_ENUM(kCpuVendor) {
//! Unknown CPU vendor.
kCpuVendorUnknown = 0,
//! No/Unknown vendor.
kCpuVendorNone = 0,
//! Intel CPU vendor.
//! Intel vendor.
kCpuVendorIntel = 1,
//! AMD CPU vendor.
//! AMD vendor.
kCpuVendorAmd = 2,
//! National Semiconductor CPU vendor (applies also to Cyrix processors).
kCpuVendorNSM = 3,
//! Transmeta CPU vendor.
kCpuVendorTransmeta = 4,
//! VIA CPU vendor.
kCpuVendorVia = 5
//! VIA vendor.
kCpuVendorVia = 3
};
// ============================================================================
@@ -51,7 +50,7 @@ ASMJIT_ENUM(kCpuVendor) {
struct BaseCpuInfo {
ASMJIT_NO_COPY(BaseCpuInfo)
//! @internal
//! \internal
enum {
kFeaturesPerUInt32 = static_cast<int>(sizeof(uint32_t)) * 8
};
@@ -135,7 +134,7 @@ struct BaseCpuInfo {
uint32_t _features[4];
};
//! @}
//! \}
} // asmjit namespace

View File

@@ -16,8 +16,8 @@
namespace asmjit {
//! @addtogroup asmjit_base_util
//! @{
//! \addtogroup asmjit_base_util
//! \{
// ============================================================================
// [asmjit::CpuTicks]
@@ -29,7 +29,7 @@ struct CpuTicks {
static ASMJIT_API uint32_t now();
};
//! @}
//! \}
} // asmjit namespace

View File

@@ -49,16 +49,10 @@ static const char* errorMessages[] = {
"Unknown instruction",
"Illegal instruction",
"Illegal addressing",
"Illegal short jump",
"Illegal displacement",
"No function defined",
"Incomplete function",
"Invalid function",
"Overlapped arguments",
"No registers",
"Overlapped registers",
"Incompatible argument",
"Incompatible return",
"Unknown error"
};

View File

@@ -11,10 +11,13 @@
// [Api-Begin]
#include "../apibegin.h"
// [Dependencies - AsmJit]
#include "../base/globals.h"
namespace asmjit {
//! @addtogroup asmjit_base_logging_and_errors
//! @{
//! \addtogroup asmjit_base_general
//! \{
// ============================================================================
// [asmjit::kError]
@@ -29,73 +32,69 @@ ASMJIT_ENUM(kError) {
//! Heap memory allocation failed.
kErrorNoHeapMemory = 1,
//! Virtual memory allocation failed.
kErrorNoVirtualMemory = 2,
//! Invalid argument.
kErrorInvalidArgument = 3,
//! Invalid state.
kErrorInvalidState = 4,
//! Unknown instruction. This happens only if instruction code is
//! out of bounds. Shouldn't happen.
kErrorAssemblerUnknownInst = 5,
//! Illegal instruction, usually generated by asmjit::Assembler
//! class when emitting instruction opcode. If this error is generated the
//! target buffer is not affected by this invalid instruction.
kErrorUnknownInst = 5,
//! Illegal instruction (Assembler).
//!
//! You can also get this status code if you are under x64 (64-bit x86) and
//! you tried to decode instruction using AH, BH, CH or DH register with REX
//! prefix. These registers can't be accessed if REX prefix is used and AsmJit
//! didn't check for this situation in intrinsics (`BaseCompiler` takes care of
//! this and rearrange registers if needed).
//! This status code can also be returned in X64 mode if AH, BH, CH or DH
//! registers have been used together with a REX prefix. The instruction
//! is not encodable in such case.
//!
//! Example of raising `kErrorAssemblerIllegalInst` error.
//! Example of raising `kErrorIllegalInst` error.
//!
//! ~~~
//! // Invalid address size.
//! a.mov(dword_ptr(eax), al);
//!
//! // Undecodable instruction - AH used with r10 that can be encoded by using
//! // REX prefix only.
//! // Undecodable instruction - AH used with R10, however R10 can only be
//! // encoded by using REX prefix, which conflicts with AH.
//! a.mov(byte_ptr(r10), ah);
//! ~~~
//!
//! @note In debug mode you get assertion failure instead of setting error
//! code.
kErrorAssemblerIllegalInst = 6,
//! Illegal addressing used (unencodable).
kErrorAssemblerIllegalAddr = 7,
//! Short jump instruction used, but displacement is out of bounds.
kErrorAssemblerIllegalShortJump = 8,
//! \note In debug mode assertion is raised instead of returning an error.
kErrorIllegalInst = 6,
//! No function defined.
kErrorCompilerNoFunc = 9,
//! Function generation is not finished by using `BaseCompiler::endFunc()`
//! or something bad happened during generation related to function. This can
//! be missing compiler node, etc...
kErrorCompilerIncompleteFunc = 10,
//! Tried to generate a function with overlapped arguments.
kErrorCompilerOverlappedArgs = 11,
//! Illegal (unencodable) addressing used (Assembler).
kErrorIllegalAddresing = 7,
//! Compiler can't allocate registers.
kErrorCompilerNoRegs = 12,
//! Compiler can't allocate registers, because they overlap.
kErrorCompilerOverlappedRegs = 13,
//! Illegal (unencodable) displacement used (Assembler).
//!
//! X86/X64
//! -------
//!
//! Short form of jump instruction has been used, but the displacement is out
//! of bounds.
kErrorIllegalDisplacement = 8,
//! Tried to call function with an incompatible argument.
kErrorCompilerIncompatibleArg = 14,
//! Incompatible return value.
kErrorCompilerIncompatibleRet = 15,
//! Invalid function (Compiler).
//!
//! Returned if no function is defined, but `make()` has been called.
kErrorInvalidFunction = 9,
//! A variable has been assigned more than once to a function argument (Compiler).
kErrorOverlappedArgs = 10,
//! Count of AsmJit status codes. Can grow in future.
kErrorCount = 16
kErrorCount = 11
};
// ============================================================================
// [asmjit::Error]
// ============================================================================
//! AsmJit error type (unsigned integer).
typedef uint32_t Error;
// ============================================================================
@@ -126,7 +125,7 @@ struct ErrorHandler {
//! Reference this error handler.
//!
//! @note This member function is provided for convenience. The default
//! \note This member function is provided for convenience. The default
//! implementation does nothing. If you are working in environment where
//! multiple `ErrorHandler` instances are used by a different code generators
//! you may provide your own functionality for reference counting. In that
@@ -135,7 +134,7 @@ struct ErrorHandler {
//! Release this error handler.
//!
//! @note This member function is provided for convenience. See `addRef()`
//! \note This member function is provided for convenience. See `addRef()`
//! for more detailed information related to reference counting.
ASMJIT_API virtual void release();
@@ -183,11 +182,13 @@ struct ErrorUtil {
static ASMJIT_API const char* asString(Error code);
};
//! \}
// ============================================================================
// [ASMJIT_PROPAGATE_ERROR]
// ============================================================================
//! @internal
//! \internal
//!
//! Used by AsmJit to return the `_Exp_` result if it's an error.
#define ASMJIT_PROPAGATE_ERROR(_Exp_) \
@@ -197,8 +198,6 @@ struct ErrorUtil {
return errval_; \
} while (0)
//! @}
} // asmjit namespace
// [Api-End]

View File

@@ -9,23 +9,15 @@
#define _ASMJIT_BASE_FUNC_H
// [Dependencies - AsmJit]
#include "../base/defs.h"
#include "../base/globals.h"
#include "../base/operand.h"
// [Api-Begin]
#include "../apibegin.h"
namespace asmjit {
//! @addtogroup asmjit_base_codegen
//! @{
// ============================================================================
// [Forward Declarations]
// ============================================================================
template<typename T>
struct FnTypeId;
//! \addtogroup asmjit_base_tree
//! \{
// ============================================================================
// [asmjit::kFuncConv]
@@ -141,24 +133,15 @@ ASMJIT_ENUM(kFuncFlags) {
ASMJIT_ENUM(kFuncDir) {
//! Arguments are passed left to right.
//!
//! This arguments direction is unusual to C programming, it's used by pascal
//! compilers and in some calling conventions by Borland compiler).
//! This arguments direction is unusual in C, however it's used in Pascal.
kFuncDirLtr = 0,
//! Arguments are passed right ro left
//!
//! This is default argument direction in C programming.
//! This is the default argument direction in C.
kFuncDirRtl = 1
};
// ============================================================================
// [asmjit::kFuncStackInvalid]
// ============================================================================
enum {
//! Invalid stack offset in function or function parameter.
kFuncStackInvalid = -1
};
// ============================================================================
// [asmjit::kFuncArg]
// ============================================================================
@@ -196,23 +179,17 @@ ASMJIT_ENUM(kFuncRet) {
};
// ============================================================================
// [asmjit::FnTypeId]
// [asmjit::kFuncStackInvalid]
// ============================================================================
//! @internal
#define ASMJIT_DECLARE_TYPE_CORE(_PtrId_) \
template<typename T> \
struct TypeId { enum { kId = static_cast<int>(::asmjit::kVarTypeInvalid) }; }; \
\
template<typename T> \
struct TypeId<T*> { enum { kId = _PtrId_ }; }
enum kFuncMisc {
//! Invalid stack offset in function or function parameter.
kFuncStackInvalid = -1
};
//! @internal
//!
//! Declare C/C++ type-id mapped to `kVarType`.
#define ASMJIT_DECLARE_TYPE_ID(_T_, _Id_) \
template<> \
struct TypeId<_T_> { enum { kId = _Id_ }; }
// ============================================================================
// [asmjit::FnTypeId]
// ============================================================================
//! Function builder 'void' type.
struct FnVoid {};
@@ -248,6 +225,20 @@ struct FnFloat {};
struct FnDouble {};
#if !defined(ASMJIT_DOCGEN)
template<typename T>
struct FnTypeId;
#define ASMJIT_DECLARE_TYPE_CORE(_PtrId_) \
template<typename T> \
struct TypeId { enum { kId = static_cast<int>(::asmjit::kVarTypeInvalid) }; }; \
\
template<typename T> \
struct TypeId<T*> { enum { kId = _PtrId_ }; }
#define ASMJIT_DECLARE_TYPE_ID(_T_, _Id_) \
template<> \
struct TypeId<_T_> { enum { kId = _Id_ }; }
ASMJIT_DECLARE_TYPE_CORE(kVarTypeIntPtr);
ASMJIT_DECLARE_TYPE_ID(void, kVarTypeInvalid);
@@ -398,7 +389,7 @@ struct FuncDecl {
//!
//! Direction should be always `kFuncDirRtl`.
//!
//! @note This is related to used calling convention, it's not affected by
//! \note This is related to used calling convention, it's not affected by
//! number of function arguments or their types.
ASMJIT_INLINE uint32_t getDirection() const { return _direction; }
@@ -471,12 +462,12 @@ struct FuncDecl {
//! Size of "Red Zone".
//!
//! @note Used by AMD64-ABI (128 bytes).
//! \note Used by AMD64-ABI (128 bytes).
uint16_t _redZoneSize;
//! Size of "Spill Zone".
//!
//! @note Used by WIN64-ABI (32 bytes).
//! \note Used by WIN64-ABI (32 bytes).
uint16_t _spillZoneSize;
//! Function arguments (including HI arguments) mapped to physical
@@ -542,6 +533,7 @@ struct FuncBuilderX : public FuncPrototype {
uint32_t _builderArgList[kFuncArgCount];
};
//! \internal
#define _TID(_T_) TypeId<_T_>::kId
//! Function builder (no args).
@@ -644,7 +636,7 @@ struct FuncBuilder10 : public FuncPrototype {
#undef _TID
//! @}
//! \}
} // asmjit namespace

View File

@@ -16,15 +16,21 @@
namespace asmjit {
//! @addtogroup asmjit_base_globals
//! @{
//! \addtogroup asmjit_base_general
//! \{
// ============================================================================
// [asmjit::kGlobals]
// ============================================================================
//! Invalid index
//!
//! Invalid index is the last possible index that is never used in practice. In
//! AsmJit it is used exclusively with strings to indicate the the length of the
//! string is not known and has to be determined.
static const size_t kInvalidIndex = ~static_cast<size_t>(0);
//! Global constants.
ASMJIT_ENUM(kGlobals) {
//! Invalid value or operand id.
kInvalidValue = 0xFFFFFFFF,
@@ -32,26 +38,20 @@ ASMJIT_ENUM(kGlobals) {
//! Invalid register index.
kInvalidReg = 0xFF,
//! Minimum reserved bytes in `Buffer`.
kBufferGrow = 32U,
//! Minimum size of assembler/compiler code buffer.
kMemAllocMinimum = 4096,
//! Host memory allocator overhead.
//!
//! The overhead is decremented from all zone allocators so the operating
//! system doesn't have allocate extra virtual page to keep tract of the
//! requested memory block.
//!
//! The number is actually a guess.
kMemAllocOverhead = sizeof(intptr_t) * 4,
//! Memory grow threshold.
//!
//! After the grow threshold is reached the capacity won't be doubled
//! anymore.
kMemAllocGrowMax = 8192 * 1024,
//! Host memory allocator overhead.
//!
//! We decrement the overhead from our pools so the host operating system
//! doesn't need allocate an extra virtual page to put the data it needs
//! to manage the requested memory block (for example if a single virtual
//! page is 4096 and we require the same memory size we decrease our
//! requirement by kMemAllocOverhead).
kMemAllocOverhead = sizeof(intptr_t) * 4,
kMemAllocGrowMax = 8192 * 1024
};
// ============================================================================
@@ -87,7 +87,21 @@ ASMJIT_ENUM(kArch) {
kArchHost64Bit = sizeof(intptr_t) >= 8
};
//! @}
// ============================================================================
// [asmjit::Ptr / SignedPtr]
// ============================================================================
//! 64-bit unsigned pointer, compatible with JIT and non-JIT generators.
//!
//! This is the preferred pointer type to use with AsmJit library. It has a
//! capability to hold any pointer for any architecture making it an ideal
//! candidate for cross-platform code generation.
typedef uint64_t Ptr;
//! 64-bit signed pointer, like \ref Ptr, but made signed.
typedef int64_t SignedPtr;
//! \}
// ============================================================================
// [asmjit::Init / NoInit]
@@ -105,17 +119,18 @@ static const _NoInit NoInit = {};
// [asmjit::Assert]
// ============================================================================
//! @addtogroup asmjit_base_logging_and_errors
//! @{
//! \addtogroup asmjit_base_general
//! \{
//! Called in debug build on assertion failure.
//!
//! @param exp Expression that failed.
//! @param file Source file name where it happened.
//! @param line Line in the source file.
//! \param exp Expression that failed.
//! \param file Source file name where it happened.
//! \param line Line in the source file.
//!
//! If you have problems with assertions put a breakpoint at assertionFailed()
//! function (asmjit/base/assert.cpp) to see what happened.
//! function (asmjit/base/globals.cpp) and check the call stack to locate the
//! failing code.
ASMJIT_API void assertionFailed(const char* exp, const char* file, int line);
#if defined(ASMJIT_DEBUG)
@@ -127,7 +142,7 @@ ASMJIT_API void assertionFailed(const char* exp, const char* file, int line);
#define ASMJIT_ASSERT(_Exp_) ASMJIT_NOP()
#endif // DEBUG
//! @}
//! \}
} // asmjit namespace
@@ -135,8 +150,8 @@ ASMJIT_API void assertionFailed(const char* exp, const char* file, int line);
// [asmjit_cast<>]
// ============================================================================
//! @addtogroup asmjit_base_util
//! @{
//! \addtogroup asmjit_base_util
//! \{
//! Cast used to cast pointer to function. It's like reinterpret_cast<>,
//! but uses internally C style cast to work with MinGW.
@@ -148,7 +163,7 @@ ASMJIT_API void assertionFailed(const char* exp, const char* file, int line);
template<typename T, typename Z>
static ASMJIT_INLINE T asmjit_cast(Z* p) { return (T)p; }
//! @}
//! \}
// [Api-End]
#include "../apiend.h"

View File

@@ -20,14 +20,14 @@
namespace asmjit {
//! @addtogroup asmjit_base_util
//! @{
//! \addtogroup asmjit_base_util
//! \{
// ============================================================================
// [asmjit::IntTraits]
// ============================================================================
//! @internal
//! \internal
template<typename T>
struct IntTraits {
enum {
@@ -53,13 +53,13 @@ struct IntUtil {
// [Float <-> Int]
// --------------------------------------------------------------------------
//! @internal
//! \internal
union Float {
int32_t i;
float f;
};
//! @internal
//! \internal
union Double {
int64_t i;
double d;
@@ -144,7 +144,7 @@ struct IntUtil {
// [AsmJit - IsInt/IsUInt]
// --------------------------------------------------------------------------
//! Get whether the given integer `x` can be casted to a signed 8-bit integer.
//! Get whether the given integer `x` can be casted to 8-bit signed integer.
template<typename T>
static ASMJIT_INLINE bool isInt8(T x) {
if (IntTraits<T>::kIsSigned)
@@ -153,7 +153,7 @@ struct IntUtil {
return x <= T(127);
}
//! Get whether the given integer `x` can be casted to an unsigned 8-bit integer.
//! Get whether the given integer `x` can be casted to 8-bit unsigned integer.
template<typename T>
static ASMJIT_INLINE bool isUInt8(T x) {
if (IntTraits<T>::kIsSigned)
@@ -162,7 +162,7 @@ struct IntUtil {
return sizeof(T) <= sizeof(uint8_t) ? true : x <= T(255);
}
//! Get whether the given integer `x` can be casted to a signed 16-bit integer.
//! Get whether the given integer `x` can be casted to 16-bit signed integer.
template<typename T>
static ASMJIT_INLINE bool isInt16(T x) {
if (IntTraits<T>::kIsSigned)
@@ -171,7 +171,7 @@ struct IntUtil {
return x >= T(0) && (sizeof(T) <= sizeof(int16_t) ? true : x <= T(32767));
}
//! Get whether the given integer `x` can be casted to an unsigned 16-bit integer.
//! Get whether the given integer `x` can be casted to 16-bit unsigned integer.
template<typename T>
static ASMJIT_INLINE bool isUInt16(T x) {
if (IntTraits<T>::kIsSigned)
@@ -180,7 +180,7 @@ struct IntUtil {
return sizeof(T) <= sizeof(uint16_t) ? true : x <= T(65535);
}
//! Get whether the given integer `x` can be casted to a signed 32-bit integer.
//! Get whether the given integer `x` can be casted to 32-bit signed integer.
template<typename T>
static ASMJIT_INLINE bool isInt32(T x) {
if (IntTraits<T>::kIsSigned)
@@ -189,7 +189,7 @@ struct IntUtil {
return x >= T(0) && (sizeof(T) <= sizeof(int32_t) ? true : x <= T(2147483647));
}
//! Get whether the given integer `x` can be casted to an unsigned 32-bit integer.
//! Get whether the given integer `x` can be casted to 32-bit unsigned integer.
template<typename T>
static ASMJIT_INLINE bool isUInt32(T x) {
if (IntTraits<T>::kIsSigned)
@@ -315,7 +315,7 @@ struct IntUtil {
// [AsmJit - FindFirstBit]
// --------------------------------------------------------------------------
//! @internal
//! \internal
static ASMJIT_INLINE uint32_t findFirstBitSlow(uint32_t mask) {
// This is a reference (slow) implementation of findFirstBit(), used when
// we don't have compiler support for this task. The implementation speed
@@ -716,7 +716,7 @@ union UInt64 {
};
};
//! @}
//! \}
} // asmjit namespace

View File

@@ -11,11 +11,6 @@
// [Dependencies - AsmJit]
#include "../build.h"
// [Dependencies - Windows]
#if defined(ASMJIT_OS_WINDOWS)
# include <windows.h>
#endif // ASMJIT_OS_WINDOWS
// [Dependencies - Posix]
#if defined(ASMJIT_OS_POSIX)
# include <pthread.h>
@@ -26,8 +21,8 @@
namespace asmjit {
//! @addtogroup asmjit_base_util
//! @{
//! \addtogroup asmjit_base_util
//! \{
// ============================================================================
// [asmjit::Lock]
@@ -80,7 +75,7 @@ struct Lock {
//! Get handle.
ASMJIT_INLINE Handle& getHandle() { return _handle; }
//! @overload
//! \overload
ASMJIT_INLINE const Handle& getHandle() const { return _handle; }
// --------------------------------------------------------------------------
@@ -95,7 +90,7 @@ struct Lock {
// [asmjit::AutoLock]
// ============================================================================
//! Scope auto locker.
//! Scoped lock.
struct AutoLock {
ASMJIT_NO_COPY(AutoLock)
@@ -121,7 +116,7 @@ struct AutoLock {
Lock& _target;
};
//! @}
//! \}
} // asmjit namespace

View File

@@ -9,7 +9,6 @@
#define _ASMJIT_BASE_LOGGER_H
// [Dependencies - AsmJit]
#include "../base/defs.h"
#include "../base/string.h"
// [Dependencies - C]
@@ -20,8 +19,8 @@
namespace asmjit {
//! @addtogroup asmjit_base_logging_and_errors
//! @{
//! \addtogroup asmjit_base_util
//! \{
// ============================================================================
// [asmjit::kLoggerOption]
@@ -156,13 +155,11 @@ struct FileLogger : public Logger {
//! Get `FILE*` stream.
//!
//! @note Return value can be `NULL`.
//! \note Return value can be `NULL`.
ASMJIT_INLINE FILE* getStream() const { return _stream; }
//! Set `FILE*` stream.
//!
//! @param stream `FILE` stream where to log output, can be set to `NULL` to
//! disable logging.
//! Set `FILE*` stream, can be set to `NULL` to disable logging, although
//! the `CodeGen` will still call `logString` even if there is no stream.
ASMJIT_API void setStream(FILE* stream);
// --------------------------------------------------------------------------
@@ -224,7 +221,7 @@ struct StringLogger : public Logger {
StringBuilder _stringBuilder;
};
//! @}
//! \}
} // asmjit namespace

View File

@@ -8,7 +8,7 @@
#define ASMJIT_EXPORTS
// [Dependencies - AsmJit]
#include "../base/defs.h"
#include "../base/operand.h"
// [Api-Begin]
#include "../apibegin.h"

View File

@@ -5,8 +5,8 @@
// Zlib - See LICENSE.md file in the package.
// [Guard]
#ifndef _ASMJIT_BASE_DEFS_H
#define _ASMJIT_BASE_DEFS_H
#ifndef _ASMJIT_BASE_OPERAND_H
#define _ASMJIT_BASE_OPERAND_H
// [Dependencies - AsmJit]
#include "../base/intutil.h"
@@ -16,9 +16,6 @@
namespace asmjit {
//! @addtogroup asmjit_base_codegen
//! @{
// ============================================================================
// [Forward Declarations]
// ============================================================================
@@ -26,6 +23,9 @@ namespace asmjit {
struct BaseAssembler;
struct BaseCompiler;
//! \addtogroup asmjit_base_general
//! \{
// ============================================================================
// [asmjit::kOperandType]
// ============================================================================
@@ -71,51 +71,6 @@ ASMJIT_ENUM(kRegClass) {
kRegClassInvalid = 0xFF
};
// ============================================================================
// [asmjit::kInstCode]
// ============================================================================
//! Instruction codes (stub).
ASMJIT_ENUM(kInstCode) {
//! No instruction.
kInstNone = 0
};
// ============================================================================
// [asmjit::kInstOptions]
// ============================================================================
//! Instruction options (stub).
ASMJIT_ENUM(kInstOptions) {
//! No instruction options.
kInstOptionNone = 0x00,
//! Emit short form of the instruction.
//!
//! X86/X64:
//!
//! Short form is mostly related to jmp and jcc instructions, but can be used
//! by other instructions supporting 8-bit or 32-bit immediates. This option
//! can be dangerous if the short jmp/jcc is required, but not encodable due
//! to large displacement, in such case an error happens and the whole
//! assembler/compiler stream is unusable.
kInstOptionShortForm = 0x01,
//! Emit long form of the instruction.
//!
//! X86/X64:
//!
//! Long form is mosrlt related to jmp and jcc instructions, but like the
//! `kInstOptionShortForm` option it can be used by other instructions
//! supporting both 8-bit and 32-bit immediates.
kInstOptionLongForm = 0x02,
//! Condition is likely to be taken (instruction).
kInstOptionTaken = 0x04,
//! Condition is unlikely to be taken (instruction).
kInstOptionNotTaken = 0x08
};
// ============================================================================
// [asmjit::kSize]
// ============================================================================
@@ -174,21 +129,21 @@ ASMJIT_ENUM(kMemType) {
// ============================================================================
ASMJIT_ENUM(kVarType) {
//! Variable is signed 8-bit integer.
//! Variable is 8-bit signed integer.
kVarTypeInt8 = 0,
//! Variable is unsigned 8-bit integer.
//! Variable is 8-bit unsigned integer.
kVarTypeUInt8 = 1,
//! Variable is signed 16-bit integer.
//! Variable is 16-bit signed integer.
kVarTypeInt16 = 2,
//! Variable is unsigned 16-bit integer.
//! Variable is 16-bit unsigned integer.
kVarTypeUInt16 = 3,
//! Variable is signed 32-bit integer.
//! Variable is 32-bit signed integer.
kVarTypeInt32 = 4,
//! Variable is unsigned 32-bit integer.
//! Variable is 32-bit unsigned integer.
kVarTypeUInt32 = 5,
//! Variable is signed 64-bit integer.
//! Variable is 64-bit signed integer.
kVarTypeInt64 = 6,
//! Variable is unsigned 64-bit integer.
//! Variable is 64-bit unsigned integer.
kVarTypeUInt64 = 7,
//! Variable is target `intptr_t`, not compatible with host `intptr_t`.
@@ -204,38 +159,17 @@ ASMJIT_ENUM(kVarType) {
//! Invalid variable type.
kVarTypeInvalid = 0xFF,
//! @internal
//! \internal
_kVarTypeIntStart = kVarTypeInt8,
//! @internal
//! \internal
_kVarTypeIntEnd = kVarTypeUIntPtr,
//! @internal
//! \internal
_kVarTypeFpStart = kVarTypeFp32,
//! @internal
//! \internal
_kVarTypeFpEnd = kVarTypeFp64
};
// ============================================================================
// [asmjit::kRelocMode]
// ============================================================================
ASMJIT_ENUM(kRelocMode) {
kRelocAbsToAbs = 0,
kRelocRelToAbs = 1,
kRelocAbsToRel = 2,
kRelocTrampoline = 3
};
// ============================================================================
// [asmjit::Ptr]
// ============================================================================
//! 64-bit signed pointer, compatible with JIT and non-JIT generators.
typedef int64_t SignedPtr;
//! 64-bit unsigned pointer, compatible with JIT and non-JIT generators.
typedef uint64_t Ptr;
// ============================================================================
// [asmjit::Operand]
// ============================================================================
@@ -246,7 +180,7 @@ struct Operand {
// [Structs]
// --------------------------------------------------------------------------
//! @internal
//! \internal
//!
//! Base operand data.
struct BaseOp {
@@ -261,11 +195,11 @@ struct Operand {
//! Operand id, identifier used by `BaseAssembler` and `BaseCompiler`.
//!
//! @note Uninitialized operand has always set id to `kInvalidValue`.
//! \note Uninitialized operand has always set id to `kInvalidValue`.
uint32_t id;
};
//! @internal
//! \internal
//!
//! Register or Variable operand data.
struct VRegOp {
@@ -299,13 +233,13 @@ struct Operand {
//! Variable type.
uint32_t vType;
//! @internal
//! \internal
//!
//! Unused.
uint32_t vUnused;
};
//! @internal
//! \internal
//!
//! Memory or Variable operand data.
struct VMemOp {
@@ -328,7 +262,7 @@ struct Operand {
int32_t displacement;
};
//! @internal
//! \internal
//!
//! Immediate operand data.
struct ImmOp {
@@ -345,24 +279,24 @@ struct Operand {
uint32_t id;
union {
//! 8x signed 8-bit immediate values.
//! 8x8-bit signed immediate values.
int8_t _i8[8];
//! 8x unsigned 8-bit immediate values.
//! 8x8-bit unsigned immediate values.
uint8_t _u8[8];
//! 4x signed 16-bit immediate values.
//! 4x16-bit signed immediate values.
int16_t _i16[4];
//! 4x unsigned 16-bit immediate values.
//! 4x16-bit unsigned immediate values.
uint16_t _u16[4];
//! 2x signed 32-bit immediate values.
//! 2x32-bit signed immediate values.
int32_t _i32[2];
//! 2x unsigned 32-bit immediate values.
//! 2x32-bit unsigned immediate values.
uint32_t _u32[2];
//! 1x signed 64-bit immediate value.
//! 1x64-bit signed immediate value.
int64_t _i64[1];
//! 1x unsigned 64-bit immediate value.
//! 1x64-bit unsigned immediate value.
uint64_t _u64[1];
//! 2x SP-FP values.
@@ -372,7 +306,7 @@ struct Operand {
} value;
};
//! @internal
//! \internal
//!
//! Label operand data.
struct LabelOp {
@@ -419,7 +353,7 @@ struct Operand {
// [Init & Copy]
// --------------------------------------------------------------------------
//! @internal
//! \internal
//!
//! Initialize operand to `other` (used by constructors).
ASMJIT_INLINE void _init(const Operand& other) {
@@ -448,7 +382,7 @@ struct Operand {
_packed[1].setPacked_2x32(u2, u3);
}
//! @internal
//! \internal
//!
//! Initialize operand to `other` (used by assign operators).
ASMJIT_INLINE void _copy(const Operand& other) {
@@ -553,8 +487,6 @@ struct Operand {
};
};
ASMJIT_VAR const Operand noOperand;
// ============================================================================
// [asmjit::OperandUtil]
// ============================================================================
@@ -578,7 +510,7 @@ struct OperandUtil {
//! Get whether the id refers to `BaseVar`.
//!
//! @note The function will never return `true` if the id is `kInvalidValue`.
//! \note The function will never return `true` if the id is `kInvalidValue`.
//! The trick is to compare a given id to -1 (kInvalidValue) so we check both
//! using only one comparison.
static ASMJIT_INLINE bool isVarId(uint32_t id) {
@@ -587,7 +519,7 @@ struct OperandUtil {
//! Get whether the id refers to `Label`.
//!
//! @note The function will never return `true` if the id is `kInvalidValue`.
//! \note The function will never return `true` if the id is `kInvalidValue`.
static ASMJIT_INLINE bool isLabelId(uint32_t id) {
return static_cast<int32_t>(id) >= 0;
}
@@ -1075,21 +1007,6 @@ struct Imm : public Operand {
}
};
//! Create signed immediate value operand.
static ASMJIT_INLINE Imm imm(int64_t val) {
return Imm(val);
}
//! Create unsigned immediate value operand.
static ASMJIT_INLINE Imm imm_u(uint64_t val) {
return Imm(static_cast<int64_t>(val));
}
//! Create void* pointer immediate value operand.
static ASMJIT_INLINE Imm imm_ptr(void* p) {
return Imm(static_cast<int64_t>((intptr_t)p));
}
// ============================================================================
// [asmjit::Label]
// ============================================================================
@@ -1164,7 +1081,30 @@ struct Label : public Operand {
ASMJIT_INLINE bool operator!=(const Label& other) const { return _base.id != other._base.id; }
};
//! @}
// ============================================================================
// [asmjit::Operand - Globals]
// ============================================================================
//! No operand, can be used to reset an operand by assignment or to refer to an
//! operand that doesn't exist.
ASMJIT_VAR const Operand noOperand;
//! Create signed immediate value operand.
static ASMJIT_INLINE Imm imm(int64_t val) {
return Imm(val);
}
//! Create unsigned immediate value operand.
static ASMJIT_INLINE Imm imm_u(uint64_t val) {
return Imm(static_cast<int64_t>(val));
}
//! Create void* pointer immediate value operand.
static ASMJIT_INLINE Imm imm_ptr(void* p) {
return Imm(static_cast<int64_t>((intptr_t)p));
}
//! \}
} // asmjit namespace
@@ -1172,4 +1112,4 @@ struct Label : public Operand {
#include "../apiend.h"
// [Guard]
#endif // _ASMJIT_BASE_DEFS_H
#endif // _ASMJIT_BASE_OPERAND_H

View File

@@ -9,7 +9,6 @@
#define _ASMJIT_BASE_PODLIST_H
// [Dependencies - AsmJit]
#include "../base/defs.h"
#include "../base/globals.h"
// [Api-Begin]
@@ -17,14 +16,14 @@
namespace asmjit {
//! @addtogroup asmjit_base_util
//! @{
//! \addtogroup asmjit_base_util
//! \{
// ============================================================================
// [asmjit::PodList<T>]
// ============================================================================
//! @internal
//! \internal
template <typename T>
struct PodList {
ASMJIT_NO_COPY(PodList<T>)
@@ -107,7 +106,7 @@ struct PodList {
Link* _last;
};
//! @}
//! \}
} // asmjit namespace

View File

@@ -9,23 +9,21 @@
#define _ASMJIT_BASE_PODVECTOR_H
// [Dependencies - AsmJit]
#include "../base/defs.h"
#include "../base/error.h"
#include "../base/globals.h"
// [Api-Begin]
#include "../apibegin.h"
namespace asmjit {
//! @addtogroup asmjit_base_util
//! @{
//! \addtogroup asmjit_base_util
//! \{
// ============================================================================
// [asmjit::PodVectorData]
// ============================================================================
//! @internal
//! \internal
struct PodVectorData {
//! Get data.
ASMJIT_INLINE void* getData() const {
@@ -42,7 +40,7 @@ struct PodVectorData {
// [asmjit::PodVectorBase]
// ============================================================================
//! @internal
//! \internal
struct PodVectorBase {
static ASMJIT_API const PodVectorData _nullData;
@@ -124,7 +122,7 @@ struct PodVector : PodVectorBase {
return static_cast<T*>(_d->getData());
}
//! @overload
//! \overload
ASMJIT_INLINE const T* getData() const {
return static_cast<const T*>(_d->getData());
}
@@ -271,7 +269,7 @@ struct PodVector : PodVectorBase {
}
};
//! @}
//! \}
} // asmjit namespace

View File

@@ -10,7 +10,6 @@
// [Dependencies - AsmJit]
#include "../base/assembler.h"
#include "../base/cpuinfo.h"
#include "../base/defs.h"
#include "../base/error.h"
#include "../base/runtime.h"
@@ -77,7 +76,7 @@ Error JitRuntime::add(void** dst, BaseAssembler* assembler) {
if (codeSize == 0) {
*dst = NULL;
return kErrorCompilerNoFunc;
return kErrorInvalidFunction;
}
void* p = _memMgr.alloc(codeSize, getAllocType());
@@ -96,6 +95,8 @@ Error JitRuntime::add(void** dst, BaseAssembler* assembler) {
// Return the code.
*dst = p;
flush(p, relocSize);
return kErrorOk;
}
@@ -103,6 +104,18 @@ Error JitRuntime::release(void* p) {
return _memMgr.release(p);
}
void JitRuntime::flush(void* p, size_t size) {
// Only useful on non-x86 architectures.
#if !defined(ASMJIT_HOST_X86) && !defined(ASMJIT_HOST_X64)
// Windows has built-in support in kernel32.dll.
#if defined(ASMJIT_OS_WINDOWS)
::FlushInstructionCache(_memMgr.getProcessHandle(), p, size);
#endif // ASMJIT_OS_WINDOWS
#endif // !ASMJIT_HOST_X86 && !ASMJIT_HOST_X64
}
} // asmjit namespace
// [Api-End]

View File

@@ -17,9 +17,6 @@
namespace asmjit {
//! @addtogroup asmjit_base_codegen
//! @{
// ============================================================================
// [Forward Declarations]
// ============================================================================
@@ -27,6 +24,9 @@ namespace asmjit {
struct BaseAssembler;
struct BaseCpuInfo;
//! \addtogroup asmjit_base_general
//! \{
// ============================================================================
// [asmjit::Runtime]
// ============================================================================
@@ -54,10 +54,12 @@ struct Runtime {
//! Get CPU information.
virtual const BaseCpuInfo* getCpuInfo() = 0;
//! Allocate a memory needed for a code generated by `BaseAssembler` and
//! Allocate a memory needed for a code generated by `assembler` and
//! relocate it to the target location.
//!
//! Returns Status code as `kError`.
//! The beginning of the memory allocated for the function is returned in
//! `dst`. Returns Status code as \ref kError, on failure `dst` is set to
//! `NULL`.
virtual Error add(void** dst, BaseAssembler* assembler) = 0;
//! Release memory allocated by `add`.
@@ -115,6 +117,19 @@ struct JitRuntime : public Runtime {
ASMJIT_API virtual Error add(void** dst, BaseAssembler* assembler);
ASMJIT_API virtual Error release(void* p);
//! Flush instruction cache.
//!
//! This member function is called after the code has been copied to the
//! destination buffer. It is only useful for JIT code generation as it
//! causes to flush the processor cache so it will not use the old data.
//!
//! Flushing is basically a NOP under X86/X64, but is needed by architectures
//! not having a transparent cache.
//!
//! This function can also be overridden to improve compatibility with tools
//! like Valgrind, but this is not an official part of AsmJit.
ASMJIT_API virtual void flush(void* p, size_t size);
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
@@ -125,7 +140,7 @@ struct JitRuntime : public Runtime {
uint32_t _allocType;
};
//! @}
//! \}
} // asmjit namespace

View File

@@ -8,7 +8,6 @@
#define ASMJIT_EXPORTS
// [Dependencies - AsmJit]
#include "../base/defs.h"
#include "../base/intutil.h"
#include "../base/string.h"

View File

@@ -9,7 +9,6 @@
#define _ASMJIT_BASE_STRING_H
// [Dependencies - AsmJit]
#include "../base/defs.h"
#include "../base/globals.h"
// [Dependencies - C]
@@ -20,14 +19,14 @@
namespace asmjit {
//! @addtogroup asmjit_base_util
//! @{
//! \addtogroup asmjit_base_util
//! \{
// ============================================================================
// [asmjit::kStringOp]
// ============================================================================
//! @internal
//! \internal
//!
//! String operation.
ASMJIT_ENUM(kStringOp) {
@@ -41,7 +40,7 @@ ASMJIT_ENUM(kStringOp) {
// [asmjit::kStringFormat]
// ============================================================================
//! @internal
//! \internal
//!
//! String format flags.
ASMJIT_ENUM(kStringFormat) {
@@ -55,8 +54,6 @@ ASMJIT_ENUM(kStringFormat) {
// [asmjit::StringUtil]
// ============================================================================
//! @internal
//!
//! String utilities.
struct StringUtil {
static ASMJIT_INLINE size_t nlen(const char* s, size_t maxlen) {
@@ -72,8 +69,6 @@ struct StringUtil {
// [asmjit::StringBuilder]
// ============================================================================
//! @internal
//!
//! String builder.
//!
//! String builder was designed to be able to build a string using append like
@@ -339,7 +334,7 @@ struct StringBuilder {
// [asmjit::StringBuilderT]
// ============================================================================
//! @internal
//! \internal
template<size_t N>
struct StringBuilderT : public StringBuilder {
ASMJIT_NO_COPY(StringBuilderT<N>)
@@ -366,7 +361,7 @@ struct StringBuilderT : public StringBuilder {
N + 1 + sizeof(intptr_t)) & ~static_cast<size_t>(sizeof(intptr_t) - 1)];
};
//! @}
//! \}
} // asmjit namespace

View File

@@ -9,15 +9,15 @@
#define _ASMJIT_BASE_VECTYPES_H
// [Dependencies - AsmJit]
#include "../base/defs.h"
#include "../base/globals.h"
// [Api-Begin]
#include "../apibegin.h"
namespace asmjit {
//! @addtogroup asmjit_base_vectypes
//! @{
//! \addtogroup asmjit_base_util
//! \{
// ============================================================================
// [asmjit::Vec64Data]
@@ -29,7 +29,7 @@ union Vec64Data {
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! Set all eight signed 8-bit integers.
//! Set all eight 8-bit signed integers.
static ASMJIT_INLINE Vec64Data fromSb(
int8_t x0, int8_t x1, int8_t x2, int8_t x3, int8_t x4, int8_t x5, int8_t x6, int8_t x7)
{
@@ -38,7 +38,7 @@ union Vec64Data {
return self;
}
//! Set all eight signed 8-bit integers.
//! Set all eight 8-bit signed integers.
static ASMJIT_INLINE Vec64Data fromSb(
int8_t x0)
{
@@ -47,7 +47,7 @@ union Vec64Data {
return self;
}
//! Set all eight unsigned 8-bit integers.
//! Set all eight 8-bit unsigned integers.
static ASMJIT_INLINE Vec64Data fromUb(
uint8_t x0, uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4, uint8_t x5, uint8_t x6, uint8_t x7)
{
@@ -56,7 +56,7 @@ union Vec64Data {
return self;
}
//! Set all eight unsigned 8-bit integers.
//! Set all eight 8-bit unsigned integers.
static ASMJIT_INLINE Vec64Data fromUb(
uint8_t x0)
{
@@ -65,7 +65,7 @@ union Vec64Data {
return self;
}
//! Set all four signed 16-bit integers.
//! Set all four 16-bit signed integers.
static ASMJIT_INLINE Vec64Data fromSw(
int16_t x0, int16_t x1, int16_t x2, int16_t x3)
{
@@ -74,7 +74,7 @@ union Vec64Data {
return self;
}
//! Set all four signed 16-bit integers.
//! Set all four 16-bit signed integers.
static ASMJIT_INLINE Vec64Data fromSw(
int16_t x0)
{
@@ -83,7 +83,7 @@ union Vec64Data {
return self;
}
//! Set all four unsigned 16-bit integers.
//! Set all four 16-bit unsigned integers.
static ASMJIT_INLINE Vec64Data fromUw(
uint16_t x0, uint16_t x1, uint16_t x2, uint16_t x3)
{
@@ -92,7 +92,7 @@ union Vec64Data {
return self;
}
//! Set all four unsigned 16-bit integers.
//! Set all four 16-bit unsigned integers.
static ASMJIT_INLINE Vec64Data fromUw(
uint16_t x0)
{
@@ -101,7 +101,7 @@ union Vec64Data {
return self;
}
//! Set all two signed 32-bit integers.
//! Set all two 32-bit signed integers.
static ASMJIT_INLINE Vec64Data fromSd(
int32_t x0, int32_t x1)
{
@@ -110,7 +110,7 @@ union Vec64Data {
return self;
}
//! Set all two signed 32-bit integers.
//! Set all two 32-bit signed integers.
static ASMJIT_INLINE Vec64Data fromSd(
int32_t x0)
{
@@ -119,7 +119,7 @@ union Vec64Data {
return self;
}
//! Set all two unsigned 32-bit integers.
//! Set all two 32-bit unsigned integers.
static ASMJIT_INLINE Vec64Data fromUd(
uint32_t x0, uint32_t x1)
{
@@ -128,7 +128,7 @@ union Vec64Data {
return self;
}
//! Set all two unsigned 32-bit integers.
//! Set all two 32-bit unsigned integers.
static ASMJIT_INLINE Vec64Data fromUd(
uint32_t x0)
{
@@ -137,7 +137,7 @@ union Vec64Data {
return self;
}
//! Set signed 64-bit integer.
//! Set 64-bit signed integer.
static ASMJIT_INLINE Vec64Data fromSq(
int64_t x0)
{
@@ -146,7 +146,7 @@ union Vec64Data {
return self;
}
//! Set unsigned 64-bit integer.
//! Set 64-bit unsigned integer.
static ASMJIT_INLINE Vec64Data fromUq(
uint64_t x0)
{
@@ -186,7 +186,7 @@ union Vec64Data {
// [Accessors]
// --------------------------------------------------------------------------
//! Set all eight signed 8-bit integers.
//! Set all eight 8-bit signed integers.
ASMJIT_INLINE void setSb(
int8_t x0, int8_t x1, int8_t x2, int8_t x3, int8_t x4, int8_t x5, int8_t x6, int8_t x7)
{
@@ -194,14 +194,14 @@ union Vec64Data {
sb[4] = x4; sb[5] = x5; sb[6] = x6; sb[7] = x7;
}
//! Set all eight signed 8-bit integers.
//! Set all eight 8-bit signed integers.
ASMJIT_INLINE void setSb(
int8_t x0)
{
setUb(static_cast<uint8_t>(x0));
}
//! Set all eight unsigned 8-bit integers.
//! Set all eight 8-bit unsigned integers.
ASMJIT_INLINE void setUb(
uint8_t x0, uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4, uint8_t x5, uint8_t x6, uint8_t x7)
{
@@ -209,7 +209,7 @@ union Vec64Data {
ub[4] = x4; ub[5] = x5; ub[6] = x6; ub[7] = x7;
}
//! Set all eight unsigned 8-bit integers.
//! Set all eight 8-bit unsigned integers.
ASMJIT_INLINE void setUb(
uint8_t x0)
{
@@ -224,28 +224,28 @@ union Vec64Data {
}
}
//! Set all four signed 16-bit integers.
//! Set all four 16-bit signed integers.
ASMJIT_INLINE void setSw(
int16_t x0, int16_t x1, int16_t x2, int16_t x3)
{
sw[0] = x0; sw[1] = x1; sw[2] = x2; sw[3] = x3;
}
//! Set all four signed 16-bit integers.
//! Set all four 16-bit signed integers.
ASMJIT_INLINE void setSw(
int16_t x0)
{
setUw(static_cast<uint16_t>(x0));
}
//! Set all four unsigned 16-bit integers.
//! Set all four 16-bit unsigned integers.
ASMJIT_INLINE void setUw(
uint16_t x0, uint16_t x1, uint16_t x2, uint16_t x3)
{
uw[0] = x0; uw[1] = x1; uw[2] = x2; uw[3] = x3;
}
//! Set all four unsigned 16-bit integers.
//! Set all four 16-bit unsigned integers.
ASMJIT_INLINE void setUw(
uint16_t x0)
{
@@ -260,42 +260,42 @@ union Vec64Data {
}
}
//! Set all two signed 32-bit integers.
//! Set all two 32-bit signed integers.
ASMJIT_INLINE void setSd(
int32_t x0, int32_t x1)
{
sd[0] = x0; sd[1] = x1;
}
//! Set all two signed 32-bit integers.
//! Set all two 32-bit signed integers.
ASMJIT_INLINE void setSd(
int32_t x0)
{
sd[0] = x0; sd[1] = x0;
}
//! Set all two unsigned 32-bit integers.
//! Set all two 32-bit unsigned integers.
ASMJIT_INLINE void setUd(
uint32_t x0, uint32_t x1)
{
ud[0] = x0; ud[1] = x1;
}
//! Set all two unsigned 32-bit integers.
//! Set all two 32-bit unsigned integers.
ASMJIT_INLINE void setUd(
uint32_t x0)
{
ud[0] = x0; ud[1] = x0;
}
//! Set signed 64-bit integer.
//! Set 64-bit signed integer.
ASMJIT_INLINE void setSq(
int64_t x0)
{
sq[0] = x0;
}
//! Set unsigned 64-bit integer.
//! Set 64-bit unsigned integer.
ASMJIT_INLINE void setUq(
uint64_t x0)
{
@@ -327,21 +327,21 @@ union Vec64Data {
// [Members]
// --------------------------------------------------------------------------
//! Array of eight signed 8-bit integers.
//! Array of eight 8-bit signed integers.
int8_t sb[8];
//! Array of eight unsigned 8-bit integers.
//! Array of eight 8-bit unsigned integers.
uint8_t ub[8];
//! Array of four signed 16-bit integers.
//! Array of four 16-bit signed integers.
int16_t sw[4];
//! Array of four unsigned 16-bit integers.
//! Array of four 16-bit unsigned integers.
uint16_t uw[4];
//! Array of two signed 32-bit integers.
//! Array of two 32-bit signed integers.
int32_t sd[2];
//! Array of two unsigned 32-bit integers.
//! Array of two 32-bit unsigned integers.
uint32_t ud[2];
//! Array of one signed 64-bit integer.
//! Array of one 64-bit signed integer.
int64_t sq[1];
//! Array of one unsigned 64-bit integer.
//! Array of one 64-bit unsigned integer.
uint64_t uq[1];
//! Array of two SP-FP values.
@@ -360,7 +360,7 @@ union Vec128Data {
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! Set all sixteen signed 8-bit integers.
//! Set all sixteen 8-bit signed integers.
static ASMJIT_INLINE Vec128Data fromSb(
int8_t x0 , int8_t x1 , int8_t x2 , int8_t x3 ,
int8_t x4 , int8_t x5 , int8_t x6 , int8_t x7 ,
@@ -372,7 +372,7 @@ union Vec128Data {
return self;
}
//! Set all sixteen signed 8-bit integers.
//! Set all sixteen 8-bit signed integers.
static ASMJIT_INLINE Vec128Data fromSb(
int8_t x0)
{
@@ -381,7 +381,7 @@ union Vec128Data {
return self;
}
//! Set all sixteen unsigned 8-bit integers.
//! Set all sixteen 8-bit unsigned integers.
static ASMJIT_INLINE Vec128Data fromUb(
uint8_t x0 , uint8_t x1 , uint8_t x2 , uint8_t x3 ,
uint8_t x4 , uint8_t x5 , uint8_t x6 , uint8_t x7 ,
@@ -393,7 +393,7 @@ union Vec128Data {
return self;
}
//! Set all sixteen unsigned 8-bit integers.
//! Set all sixteen 8-bit unsigned integers.
static ASMJIT_INLINE Vec128Data fromUb(
uint8_t x0)
{
@@ -402,7 +402,7 @@ union Vec128Data {
return self;
}
//! Set all eight signed 16-bit integers.
//! Set all eight 16-bit signed integers.
static ASMJIT_INLINE Vec128Data fromSw(
int16_t x0, int16_t x1, int16_t x2, int16_t x3, int16_t x4, int16_t x5, int16_t x6, int16_t x7)
{
@@ -411,7 +411,7 @@ union Vec128Data {
return self;
}
//! Set all eight signed 16-bit integers.
//! Set all eight 16-bit signed integers.
static ASMJIT_INLINE Vec128Data fromSw(
int16_t x0)
{
@@ -420,7 +420,7 @@ union Vec128Data {
return self;
}
//! Set all eight unsigned 16-bit integers.
//! Set all eight 16-bit unsigned integers.
static ASMJIT_INLINE Vec128Data fromUw(
uint16_t x0, uint16_t x1, uint16_t x2, uint16_t x3, uint16_t x4, uint16_t x5, uint16_t x6, uint16_t x7)
{
@@ -429,7 +429,7 @@ union Vec128Data {
return self;
}
//! Set all eight unsigned 16-bit integers.
//! Set all eight 16-bit unsigned integers.
static ASMJIT_INLINE Vec128Data fromUw(
uint16_t x0)
{
@@ -438,7 +438,7 @@ union Vec128Data {
return self;
}
//! Set all four signed 32-bit integers.
//! Set all four 32-bit signed integers.
static ASMJIT_INLINE Vec128Data fromSd(
int32_t x0, int32_t x1, int32_t x2, int32_t x3)
{
@@ -447,7 +447,7 @@ union Vec128Data {
return self;
}
//! Set all four signed 32-bit integers.
//! Set all four 32-bit signed integers.
static ASMJIT_INLINE Vec128Data fromSd(
int32_t x0)
{
@@ -456,7 +456,7 @@ union Vec128Data {
return self;
}
//! Set all four unsigned 32-bit integers.
//! Set all four 32-bit unsigned integers.
static ASMJIT_INLINE Vec128Data fromUd(
uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3)
{
@@ -465,7 +465,7 @@ union Vec128Data {
return self;
}
//! Set all four unsigned 32-bit integers.
//! Set all four 32-bit unsigned integers.
static ASMJIT_INLINE Vec128Data fromUd(
uint32_t x0)
{
@@ -474,7 +474,7 @@ union Vec128Data {
return self;
}
//! Set all two signed 64-bit integers.
//! Set all two 64-bit signed integers.
static ASMJIT_INLINE Vec128Data fromSq(
int64_t x0, int64_t x1)
{
@@ -483,7 +483,7 @@ union Vec128Data {
return self;
}
//! Set all two signed 64-bit integers.
//! Set all two 64-bit signed integers.
static ASMJIT_INLINE Vec128Data fromSq(
int64_t x0)
{
@@ -492,7 +492,7 @@ union Vec128Data {
return self;
}
//! Set all two unsigned 64-bit integers.
//! Set all two 64-bit unsigned integers.
static ASMJIT_INLINE Vec128Data fromUq(
uint64_t x0, uint64_t x1)
{
@@ -501,7 +501,7 @@ union Vec128Data {
return self;
}
//! Set all two unsigned 64-bit integers.
//! Set all two 64-bit unsigned integers.
static ASMJIT_INLINE Vec128Data fromUq(
uint64_t x0)
{
@@ -550,7 +550,7 @@ union Vec128Data {
// [Accessors]
// --------------------------------------------------------------------------
//! Set all sixteen signed 8-bit integers.
//! Set all sixteen 8-bit signed integers.
ASMJIT_INLINE void setSb(
int8_t x0 , int8_t x1 , int8_t x2 , int8_t x3 ,
int8_t x4 , int8_t x5 , int8_t x6 , int8_t x7 ,
@@ -563,14 +563,14 @@ union Vec128Data {
sb[12] = x12; sb[13] = x13; sb[14] = x14; sb[15] = x15;
}
//! Set all sixteen signed 8-bit integers.
//! Set all sixteen 8-bit signed integers.
ASMJIT_INLINE void setSb(
int8_t x0)
{
setUb(static_cast<uint8_t>(x0));
}
//! Set all sixteen unsigned 8-bit integers.
//! Set all sixteen 8-bit unsigned integers.
ASMJIT_INLINE void setUb(
uint8_t x0 , uint8_t x1 , uint8_t x2 , uint8_t x3 ,
uint8_t x4 , uint8_t x5 , uint8_t x6 , uint8_t x7 ,
@@ -583,7 +583,7 @@ union Vec128Data {
ub[12] = x12; ub[13] = x13; ub[14] = x14; ub[15] = x15;
}
//! Set all sixteen unsigned 8-bit integers.
//! Set all sixteen 8-bit unsigned integers.
ASMJIT_INLINE void setUb(
uint8_t x0)
{
@@ -601,7 +601,7 @@ union Vec128Data {
}
}
//! Set all eight signed 16-bit integers.
//! Set all eight 16-bit signed integers.
ASMJIT_INLINE void setSw(
int16_t x0, int16_t x1, int16_t x2, int16_t x3, int16_t x4, int16_t x5, int16_t x6, int16_t x7)
{
@@ -609,14 +609,14 @@ union Vec128Data {
sw[4] = x4; sw[5] = x5; sw[6] = x6; sw[7] = x7;
}
//! Set all eight signed 16-bit integers.
//! Set all eight 16-bit signed integers.
ASMJIT_INLINE void setSw(
int16_t x0)
{
setUw(static_cast<uint16_t>(x0));
}
//! Set all eight unsigned 16-bit integers.
//! Set all eight 16-bit unsigned integers.
ASMJIT_INLINE void setUw(
uint16_t x0, uint16_t x1, uint16_t x2, uint16_t x3, uint16_t x4, uint16_t x5, uint16_t x6, uint16_t x7)
{
@@ -624,7 +624,7 @@ union Vec128Data {
uw[4] = x4; uw[5] = x5; uw[6] = x6; uw[7] = x7;
}
//! Set all eight unsigned 16-bit integers.
//! Set all eight 16-bit unsigned integers.
ASMJIT_INLINE void setUw(
uint16_t x0)
{
@@ -642,28 +642,28 @@ union Vec128Data {
}
}
//! Set all four signed 32-bit integers.
//! Set all four 32-bit signed integers.
ASMJIT_INLINE void setSd(
int32_t x0, int32_t x1, int32_t x2, int32_t x3)
{
sd[0] = x0; sd[1] = x1; sd[2] = x2; sd[3] = x3;
}
//! Set all four signed 32-bit integers.
//! Set all four 32-bit signed integers.
ASMJIT_INLINE void setSd(
int32_t x0)
{
setUd(static_cast<uint32_t>(x0));
}
//! Set all four unsigned 32-bit integers.
//! Set all four 32-bit unsigned integers.
ASMJIT_INLINE void setUd(
uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3)
{
ud[0] = x0; ud[1] = x1; ud[2] = x2; ud[3] = x3;
}
//! Set all four unsigned 32-bit integers.
//! Set all four 32-bit unsigned integers.
ASMJIT_INLINE void setUd(
uint32_t x0)
{
@@ -680,28 +680,28 @@ union Vec128Data {
}
}
//! Set all two signed 64-bit integers.
//! Set all two 64-bit signed integers.
ASMJIT_INLINE void setSq(
int64_t x0, int64_t x1)
{
sq[0] = x0; sq[1] = x1;
}
//! Set all two signed 64-bit integers.
//! Set all two 64-bit signed integers.
ASMJIT_INLINE void setSq(
int64_t x0)
{
sq[0] = x0; sq[1] = x0;
}
//! Set all two unsigned 64-bit integers.
//! Set all two 64-bit unsigned integers.
ASMJIT_INLINE void setUq(
uint64_t x0, uint64_t x1)
{
uq[0] = x0; uq[1] = x1;
}
//! Set all two unsigned 64-bit integers.
//! Set all two 64-bit unsigned integers.
ASMJIT_INLINE void setUq(
uint64_t x0)
{
@@ -740,21 +740,21 @@ union Vec128Data {
// [Members]
// --------------------------------------------------------------------------
//! Array of sixteen signed 8-bit integers.
//! Array of sixteen 8-bit signed integers.
int8_t sb[16];
//! Array of sixteen unsigned 8-bit integers.
//! Array of sixteen 8-bit unsigned integers.
uint8_t ub[16];
//! Array of eight signed 16-bit integers.
//! Array of eight 16-bit signed integers.
int16_t sw[8];
//! Array of eight unsigned 16-bit integers.
//! Array of eight 16-bit unsigned integers.
uint16_t uw[8];
//! Array of four signed 32-bit integers.
//! Array of four 32-bit signed integers.
int32_t sd[4];
//! Array of four unsigned 32-bit integers.
//! Array of four 32-bit unsigned integers.
uint32_t ud[4];
//! Array of two signed 64-bit integers.
//! Array of two 64-bit signed integers.
int64_t sq[2];
//! Array of two unsigned 64-bit integers.
//! Array of two 64-bit unsigned integers.
uint64_t uq[2];
//! Array of four 32-bit single precision floating points.
@@ -773,7 +773,7 @@ union Vec256Data {
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! Set all thirty two signed 8-bit integers.
//! Set all thirty two 8-bit signed integers.
static ASMJIT_INLINE Vec256Data fromSb(
int8_t x0 , int8_t x1 , int8_t x2 , int8_t x3 ,
int8_t x4 , int8_t x5 , int8_t x6 , int8_t x7 ,
@@ -791,7 +791,7 @@ union Vec256Data {
return self;
}
//! Set all thirty two signed 8-bit integers.
//! Set all thirty two 8-bit signed integers.
static ASMJIT_INLINE Vec256Data fromSb(
int8_t x0)
{
@@ -800,7 +800,7 @@ union Vec256Data {
return self;
}
//! Set all thirty two unsigned 8-bit integers.
//! Set all thirty two 8-bit unsigned integers.
static ASMJIT_INLINE Vec256Data fromUb(
uint8_t x0 , uint8_t x1 , uint8_t x2 , uint8_t x3 ,
uint8_t x4 , uint8_t x5 , uint8_t x6 , uint8_t x7 ,
@@ -818,7 +818,7 @@ union Vec256Data {
return self;
}
//! Set all thirty two unsigned 8-bit integers.
//! Set all thirty two 8-bit unsigned integers.
static ASMJIT_INLINE Vec256Data fromUb(
uint8_t x0)
{
@@ -827,7 +827,7 @@ union Vec256Data {
return self;
}
//! Set all sixteen signed 16-bit integers.
//! Set all sixteen 16-bit signed integers.
static ASMJIT_INLINE Vec256Data fromSw(
int16_t x0, int16_t x1, int16_t x2 , int16_t x3 , int16_t x4 , int16_t x5 , int16_t x6 , int16_t x7 ,
int16_t x8, int16_t x9, int16_t x10, int16_t x11, int16_t x12, int16_t x13, int16_t x14, int16_t x15)
@@ -837,7 +837,7 @@ union Vec256Data {
return self;
}
//! Set all sixteen signed 16-bit integers.
//! Set all sixteen 16-bit signed integers.
static ASMJIT_INLINE Vec256Data fromSw(
int16_t x0)
{
@@ -846,7 +846,7 @@ union Vec256Data {
return self;
}
//! Set all sixteen unsigned 16-bit integers.
//! Set all sixteen 16-bit unsigned integers.
static ASMJIT_INLINE Vec256Data fromUw(
uint16_t x0, uint16_t x1, uint16_t x2 , uint16_t x3 , uint16_t x4 , uint16_t x5 , uint16_t x6 , uint16_t x7 ,
uint16_t x8, uint16_t x9, uint16_t x10, uint16_t x11, uint16_t x12, uint16_t x13, uint16_t x14, uint16_t x15)
@@ -856,7 +856,7 @@ union Vec256Data {
return self;
}
//! Set all sixteen unsigned 16-bit integers.
//! Set all sixteen 16-bit unsigned integers.
static ASMJIT_INLINE Vec256Data fromUw(
uint16_t x0)
{
@@ -865,7 +865,7 @@ union Vec256Data {
return self;
}
//! Set all eight signed 32-bit integers.
//! Set all eight 32-bit signed integers.
static ASMJIT_INLINE Vec256Data fromSd(
int32_t x0, int32_t x1, int32_t x2, int32_t x3,
int32_t x4, int32_t x5, int32_t x6, int32_t x7)
@@ -875,7 +875,7 @@ union Vec256Data {
return self;
}
//! Set all eight signed 32-bit integers.
//! Set all eight 32-bit signed integers.
static ASMJIT_INLINE Vec256Data fromSd(
int32_t x0)
{
@@ -884,7 +884,7 @@ union Vec256Data {
return self;
}
//! Set all eight unsigned 32-bit integers.
//! Set all eight 32-bit unsigned integers.
static ASMJIT_INLINE Vec256Data fromUd(
uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3,
uint32_t x4, uint32_t x5, uint32_t x6, uint32_t x7)
@@ -894,7 +894,7 @@ union Vec256Data {
return self;
}
//! Set all eight unsigned 32-bit integers.
//! Set all eight 32-bit unsigned integers.
static ASMJIT_INLINE Vec256Data fromUd(
uint32_t x0)
{
@@ -903,7 +903,7 @@ union Vec256Data {
return self;
}
//! Set all four signed 64-bit integers.
//! Set all four 64-bit signed integers.
static ASMJIT_INLINE Vec256Data fromSq(
int64_t x0, int64_t x1, int64_t x2, int64_t x3)
{
@@ -912,7 +912,7 @@ union Vec256Data {
return self;
}
//! Set all four signed 64-bit integers.
//! Set all four 64-bit signed integers.
static ASMJIT_INLINE Vec256Data fromSq(
int64_t x0)
{
@@ -921,7 +921,7 @@ union Vec256Data {
return self;
}
//! Set all four unsigned 64-bit integers.
//! Set all four 64-bit unsigned integers.
static ASMJIT_INLINE Vec256Data fromUq(
uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3)
{
@@ -930,7 +930,7 @@ union Vec256Data {
return self;
}
//! Set all four unsigned 64-bit integers.
//! Set all four 64-bit unsigned integers.
static ASMJIT_INLINE Vec256Data fromUq(
uint64_t x0)
{
@@ -980,7 +980,7 @@ union Vec256Data {
// [Accessors]
// --------------------------------------------------------------------------
//! Set all thirty two signed 8-bit integers.
//! Set all thirty two 8-bit signed integers.
ASMJIT_INLINE void setSb(
int8_t x0 , int8_t x1 , int8_t x2 , int8_t x3 ,
int8_t x4 , int8_t x5 , int8_t x6 , int8_t x7 ,
@@ -1001,14 +1001,14 @@ union Vec256Data {
sb[28] = x28; sb[29] = x29; sb[30] = x30; sb[31] = x31;
}
//! Set all thirty two signed 8-bit integers.
//! Set all thirty two 8-bit signed integers.
ASMJIT_INLINE void setSb(
int8_t x0)
{
setUb(static_cast<uint8_t>(x0));
}
//! Set all thirty two unsigned 8-bit integers.
//! Set all thirty two 8-bit unsigned integers.
ASMJIT_INLINE void setUb(
uint8_t x0 , uint8_t x1 , uint8_t x2 , uint8_t x3 ,
uint8_t x4 , uint8_t x5 , uint8_t x6 , uint8_t x7 ,
@@ -1029,7 +1029,7 @@ union Vec256Data {
ub[28] = x28; ub[29] = x29; ub[30] = x30; ub[31] = x31;
}
//! Set all thirty two unsigned 8-bit integers.
//! Set all thirty two 8-bit unsigned integers.
ASMJIT_INLINE void setUb(
uint8_t x0)
{
@@ -1053,7 +1053,7 @@ union Vec256Data {
}
}
//! Set all sixteen signed 16-bit integers.
//! Set all sixteen 16-bit signed integers.
ASMJIT_INLINE void setSw(
int16_t x0, int16_t x1, int16_t x2, int16_t x3, int16_t x4, int16_t x5, int16_t x6, int16_t x7,
int16_t x8, int16_t x9, int16_t x10, int16_t x11, int16_t x12, int16_t x13, int16_t x14, int16_t x15)
@@ -1064,14 +1064,14 @@ union Vec256Data {
sw[12] = x12; sw[13] = x13; sw[14] = x14; sw[15] = x15;
}
//! Set all sixteen signed 16-bit integers.
//! Set all sixteen 16-bit signed integers.
ASMJIT_INLINE void setSw(
int16_t x0)
{
setUw(static_cast<uint16_t>(x0));
}
//! Set all sixteen unsigned 16-bit integers.
//! Set all sixteen 16-bit unsigned integers.
ASMJIT_INLINE void setUw(
uint16_t x0, uint16_t x1, uint16_t x2 , uint16_t x3 , uint16_t x4 , uint16_t x5 , uint16_t x6 , uint16_t x7 ,
uint16_t x8, uint16_t x9, uint16_t x10, uint16_t x11, uint16_t x12, uint16_t x13, uint16_t x14, uint16_t x15)
@@ -1082,7 +1082,7 @@ union Vec256Data {
uw[12] = x12; uw[13] = x13; uw[14] = x14; uw[15] = x15;
}
//! Set all eight unsigned 16-bit integers.
//! Set all eight 16-bit unsigned integers.
ASMJIT_INLINE void setUw(
uint16_t x0)
{
@@ -1106,7 +1106,7 @@ union Vec256Data {
}
}
//! Set all eight signed 32-bit integers.
//! Set all eight 32-bit signed integers.
ASMJIT_INLINE void setSd(
int32_t x0, int32_t x1, int32_t x2, int32_t x3,
int32_t x4, int32_t x5, int32_t x6, int32_t x7)
@@ -1115,14 +1115,14 @@ union Vec256Data {
sd[4] = x4; sd[5] = x5; sd[6] = x6; sd[7] = x7;
}
//! Set all eight signed 32-bit integers.
//! Set all eight 32-bit signed integers.
ASMJIT_INLINE void setSd(
int32_t x0)
{
setUd(static_cast<uint32_t>(x0));
}
//! Set all eight unsigned 32-bit integers.
//! Set all eight 32-bit unsigned integers.
ASMJIT_INLINE void setUd(
uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3,
uint32_t x4, uint32_t x5, uint32_t x6, uint32_t x7)
@@ -1131,7 +1131,7 @@ union Vec256Data {
ud[4] = x4; ud[5] = x5; ud[6] = x6; ud[7] = x7;
}
//! Set all eight unsigned 32-bit integers.
//! Set all eight 32-bit unsigned integers.
ASMJIT_INLINE void setUd(
uint32_t x0)
{
@@ -1154,28 +1154,28 @@ union Vec256Data {
}
}
//! Set all four signed 64-bit integers.
//! Set all four 64-bit signed integers.
ASMJIT_INLINE void setSq(
int64_t x0, int64_t x1, int64_t x2, int64_t x3)
{
sq[0] = x0; sq[1] = x1; sq[2] = x2; sq[3] = x3;
}
//! Set all four signed 64-bit integers.
//! Set all four 64-bit signed integers.
ASMJIT_INLINE void setSq(
int64_t x0)
{
sq[0] = x0; sq[1] = x0; sq[2] = x0; sq[3] = x0;
}
//! Set all four unsigned 64-bit integers.
//! Set all four 64-bit unsigned integers.
ASMJIT_INLINE void setUq(
uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3)
{
uq[0] = x0; uq[1] = x1; uq[2] = x2; uq[3] = x3;
}
//! Set all four unsigned 64-bit integers.
//! Set all four 64-bit unsigned integers.
ASMJIT_INLINE void setUq(
uint64_t x0)
{
@@ -1217,21 +1217,21 @@ union Vec256Data {
// [Members]
// --------------------------------------------------------------------------
//! Array of thirty two signed 8-bit integers.
//! Array of thirty two 8-bit signed integers.
int8_t sb[32];
//! Array of thirty two unsigned 8-bit integers.
//! Array of thirty two 8-bit unsigned integers.
uint8_t ub[32];
//! Array of sixteen signed 16-bit integers.
//! Array of sixteen 16-bit signed integers.
int16_t sw[16];
//! Array of sixteen unsigned 16-bit integers.
//! Array of sixteen 16-bit unsigned integers.
uint16_t uw[16];
//! Array of eight signed 32-bit integers.
//! Array of eight 32-bit signed integers.
int32_t sd[8];
//! Array of eight unsigned 32-bit integers.
//! Array of eight 32-bit unsigned integers.
uint32_t ud[8];
//! Array of four signed 64-bit integers.
//! Array of four 64-bit signed integers.
int64_t sq[4];
//! Array of four unsigned 64-bit integers.
//! Array of four 64-bit unsigned integers.
uint64_t uq[4];
//! Array of eight 32-bit single precision floating points.
@@ -1240,7 +1240,7 @@ union Vec256Data {
double df[4];
};
//! @}
//! \}
} // asmjit namespace

View File

@@ -14,11 +14,6 @@
#include "../base/lock.h"
#include "../base/vmem.h"
// [Dependencies - Windows]
#if defined(ASMJIT_OS_WINDOWS)
# include <windows.h>
#endif // ASMJIT_OS_WINDOWS
// [Dependencies - Posix]
#if defined(ASMJIT_OS_POSIX)
# include <sys/types.h>
@@ -190,12 +185,12 @@ void VMemUtil::release(void* addr, size_t length) {
// [VMem - Ops]
// ============================================================================
//! @internal
//! \internal
enum {
kBitsPerEntity = (sizeof(size_t) * 8)
};
//! @internal
//! \internal
//!
//! Set `len` bits in `buf` starting at `index` bit index.
static void _SetBits(size_t* buf, size_t index, size_t len) {
@@ -231,7 +226,7 @@ static void _SetBits(size_t* buf, size_t index, size_t len) {
#define M_DIV(x, y) ((x) / (y))
#define M_MOD(x, y) ((x) % (y))
//! @internal
//! \internal
//!
//! Base red-black tree node.
struct RbNode {
@@ -255,7 +250,7 @@ struct RbNode {
uint8_t* mem;
};
//! @internal
//! \internal
//!
//! Get whether the node is red (NULL or node with red flag).
static ASMJIT_INLINE bool rbIsRed(RbNode* node) {
@@ -303,7 +298,7 @@ struct MemNode : public RbNode {
// [asmjit::PermanentNode]
// ============================================================================
//! @internal
//! \internal
//!
//! Permanent node.
struct PermanentNode {
@@ -330,7 +325,7 @@ struct PermanentNode {
// [asmjit::VMemPrivate]
// ============================================================================
//! @internal
//! \internal
struct VMemPrivate {
// --------------------------------------------------------------------------
// [Construction / Destruction]

View File

@@ -9,21 +9,15 @@
#define _ASMJIT_BASE_VMEM_H
// [Dependencies]
#include "../base/defs.h"
#include "../base/error.h"
// [Dependencies - Windows]
#if defined(ASMJIT_OS_WINDOWS)
# include <windows.h>
#endif // ASMJIT_OS_WINDOWS
// [Api-Begin]
#include "../apibegin.h"
namespace asmjit {
//! @addtogroup asmjit_base_util
//! @{
//! \addtogroup asmjit_base_util
//! \{
// ============================================================================
// [asmjit::kVMemAlloc]
@@ -72,12 +66,12 @@ struct VMemUtil {
#if defined(ASMJIT_OS_WINDOWS)
//! Allocate virtual memory of `hProcess`.
//!
//! @note This function is Windows specific.
//! \note This function is Windows specific.
static ASMJIT_API void* allocProcessMemory(HANDLE hProcess, size_t length, size_t* allocated, bool canExecute);
//! Free virtual memory of `hProcess`.
//!
//! @note This function is Windows specific.
//! \note This function is Windows specific.
static ASMJIT_API void releaseProcessMemory(HANDLE hProcess, void* addr, size_t length);
#endif // ASMJIT_OS_WINDOWS
};
@@ -130,7 +124,7 @@ struct VMemMgr {
//! Get whether to keep allocated memory after the `VMemMgr` is destroyed.
//!
//! @sa `setKeepVirtualMemory()`.
//! \sa \ref setKeepVirtualMemory.
ASMJIT_API bool getKeepVirtualMemory() const;
//! Set whether to keep allocated memory after memory manager is
@@ -142,9 +136,9 @@ struct VMemMgr {
//! VMemMgr destructor. After destruction all internal
//! structures are freed, only the process virtual memory remains.
//!
//! @note Memory allocated with kVMemAllocPermanent is always kept.
//! \note Memory allocated with kVMemAllocPermanent is always kept.
//!
//! @sa `getKeepVirtualMemory()`.
//! \sa \ref getKeepVirtualMemory.
ASMJIT_API void setKeepVirtualMemory(bool keepVirtualMemory);
// --------------------------------------------------------------------------
@@ -168,13 +162,13 @@ struct VMemMgr {
// [Members]
// --------------------------------------------------------------------------
//! @internal
//! \internal
//!
//! Pointer to private data hidden out of the public API.
void* _d;
};
//! @}
//! \}
} // asmjit namespace

View File

@@ -8,7 +8,6 @@
#define ASMJIT_EXPORTS
// [Dependencies - AsmJit]
#include "../base/defs.h"
#include "../base/intutil.h"
#include "../base/zone.h"

View File

@@ -16,8 +16,8 @@
namespace asmjit {
//! @addtogroup asmjit_base_util
//! @{
//! \addtogroup asmjit_base_util
//! \{
// ============================================================================
// [asmjit::Zone]
@@ -32,7 +32,7 @@ struct Zone {
// [Chunk]
// --------------------------------------------------------------------------
//! @internal
//! \internal
//!
//! One allocated chunk of memory.
struct Chunk {
@@ -56,33 +56,37 @@ struct Zone {
//! Create a new instance of `Zone` allocator.
//!
//! @param chunkSize Default size of the first chunk.
//! The `chunkSize` parameter describes the size of the chunk. If `alloc()`
//! requires more memory than `chunkSize` then a bigger chunk will be
//! allocated, however `chunkSize` will not be changed.
ASMJIT_API Zone(size_t chunkSize);
//! Destroy `Zone` instance.
//!
//! Destructor released all chunks allocated by `Zone`. The `reset()` member
//! function does the same without actually destroying `Zone` object itself.
ASMJIT_API ~Zone();
// --------------------------------------------------------------------------
// [Clear / Reset]
// --------------------------------------------------------------------------
//! Free all allocated memory except first block that remains for reuse.
//! Reset the `Zone` releasing all chunks allocated.
//!
//! Note that this method will invalidate all instances using this memory
//! allocated by this zone instance.
//! Calling `clear()` will release all chunks allocated by `Zone` except the
//! first one that will be reused if needed.
ASMJIT_API void clear();
//! Free all allocated memory at once.
//! Reset the `Zone` releasing all chunks allocated.
//!
//! Note that this method will invalidate all instances using this memory
//! allocated by this zone instance.
//! Calling `reset()` will release all chunks allocated by `Zone`.
ASMJIT_API void reset();
// --------------------------------------------------------------------------
// [Accessors]
// --------------------------------------------------------------------------
//! Get (default) chunk size.
//! Get chunk size.
ASMJIT_INLINE size_t getChunkSize() const { return _chunkSize; }
// --------------------------------------------------------------------------
@@ -140,7 +144,7 @@ struct Zone {
return static_cast<T*>(alloc(size));
}
//! @internal
//! \internal
ASMJIT_API void* _alloc(size_t size);
//! Allocate `size` bytes of zeroed memory.
@@ -158,7 +162,7 @@ struct Zone {
return (void*)p;
}
//! @internal
//! \internal
ASMJIT_API void* _calloc(size_t size);
//! Helper to duplicate data.
@@ -180,7 +184,7 @@ struct Zone {
size_t _chunkSize;
};
//! @}
//! \}
} // asmjit namespace

View File

@@ -31,16 +31,6 @@
// [Dependencies - C++]
#include <new>
// ============================================================================
// [asmjit::build - Documentation]
// ============================================================================
#if defined(ASMJIT_DOCGEN)
# define ASMJIT_BUILD_X86
# define ASMJIT_BUILD_X64
# define ASMJIT_API
#endif // ASMJIT_DOCGEN
// ============================================================================
// [asmjit::build - OS]
// ============================================================================

View File

@@ -70,6 +70,11 @@ uint32_t WinRemoteRuntime::add(void** dest, BaseAssembler* assembler) {
return kErrorOk;
}
// NOP.
Error WinRemoteRuntime::release(void* p) {
return kErrorOk;
}
} // contrib namespace
} // asmjit namespace

View File

@@ -17,6 +17,9 @@
namespace asmjit {
namespace contrib {
//! \addtogroup asmjit_contrib
//! \{
// ============================================================================
// [asmjit::contrib::WinRemoteRuntime]
// ============================================================================
@@ -54,6 +57,7 @@ struct WinRemoteRuntime : public Runtime {
// --------------------------------------------------------------------------
ASMJIT_API virtual uint32_t add(void** dest, BaseAssembler* assembler);
ASMJIT_API virtual Error release(void* p);
// --------------------------------------------------------------------------
// [Members]
@@ -63,6 +67,8 @@ struct WinRemoteRuntime : public Runtime {
VMemMgr _memMgr;
};
//! \}
} // contrib namespace
} // asmjit namespace

View File

@@ -8,121 +8,16 @@
#ifndef _ASMJIT_X86_H
#define _ASMJIT_X86_H
// ============================================================================
// [asmjit_x86x64]
// ============================================================================
//! @defgroup asmjit_x86x64 X86/X64
//!
//! @brief X86/X64 API
// ============================================================================
// [asmjit_x86x64_codegen]
// ============================================================================
//! @defgroup asmjit_x86x64_codegen Code Generation (X86/X64)
//! @ingroup asmjit_x86x64
//!
//! @brief Low-level and high-level code generation.
// ============================================================================
// [asmjit_x86x64_cpu_info]
// ============================================================================
//! @defgroup asmjit_x86x64_cpu_info CPU Information (X86/X64)
//! @ingroup asmjit_x86x64
//!
//! @brief CPU information specific to X86/X64 architecture.
//!
//! The CPUID instruction can be used to get an exhaustive information related
//! to 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 `CpuInfo` extends `BaseCpuInfo` 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 `CpuInfo` 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 `CpuInfo` and setting
//! up its members. `CpuUtil::detect` can be used to detect CPU features into
//! an existing `CpuInfo` instance - it may become handly if only one property
//! has to be turned on/off.
//!
//! If the high-level interface `CpuInfo` offers is not enough there is also
//! `CpuUtil::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;
//! using namespace asmjit::host;
//!
//! // Get `CpuInfo` global instance.
//! const CpuInfo* cpuInfo = CpuInfo::getHost();
//!
//! if (cpuInfo->hasFeature(kCpuFeatureSse2)) {
//! // Processor has SSE2.
//! }
//! else if (cpuInfo->hasFeature(kCpuFeatureMmx)) {
//! // Processor doesn't have SSE2, but has MMX.
//! }
//! else {
//! // An archaic processor, it's a wonder AsmJit works here!
//! }
//! ~~~
//!
//! The next example shows how to call CPUID directly:
//!
//! ~~~
//! using namespace asmjit;
//!
//! // The result of CPUID call.
//! CpuId out;
//!
//! // Call CPUID, first two arguments are passed in EAX/ECX.
//! CpuUtil::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);
//! ~~~
//!
//! @sa @ref asmjit_base_cpu_info
// ============================================================================
// [asmjit_x86x64_constants]
// ============================================================================
//! @defgroup asmjit_x86x64_constants Constants (X86/X64)
//! @ingroup asmjit_x86x64
//!
//! @brief Constants and definitions specific to X86/X64 architecture.
// ============================================================================
// [Dependencies - AsmJit]
// ============================================================================
#include "base.h"
#include "x86/x86assembler.h"
#include "x86/x86compiler.h"
#include "x86/x86cpuinfo.h"
#include "x86/x86defs.h"
#include "x86/x86func.h"
#include "x86/x86inst.h"
#include "x86/x86operand.h"
#include "x86/x86util.h"
// [Guard]
#endif // _ASMJIT_X86_H

View File

@@ -19,7 +19,6 @@
#include "../base/vmem.h"
#include "../x86/x86assembler.h"
#include "../x86/x86cpuinfo.h"
#include "../x86/x86defs.h"
// [Api-Begin]
#include "../apibegin.h"
@@ -58,7 +57,7 @@ enum kVexVVVV {
kVexVVVVMask = 0xF << kVexVVVVShift
};
//! @internal
//! \internal
//!
//! Instruction 2-byte/3-byte opcode prefix definition.
struct OpCodeMM {
@@ -66,7 +65,7 @@ struct OpCodeMM {
uint8_t data[3];
};
//! @internal
//! \internal
//!
//! Mandatory prefixes encoded in 'asmjit' opcode [66, F3, F2] and asmjit
//! extensions
@@ -81,7 +80,7 @@ static const uint8_t x86OpCodePP[8] = {
0x9B
};
//! @internal
//! \internal
//!
//! Instruction 2-byte/3-byte opcode prefix data.
static const OpCodeMM x86OpCodeMM[] = {
@@ -111,7 +110,7 @@ static const uint8_t x86OpCodePopSeg[8] = { 0x00, 0x07, 0x00, 0x17, 0x1F, 0xA1,
// [asmjit::X64TrampolineWriter]
// ============================================================================
//! @internal
//! \internal
//!
//! Trampoline writer.
struct X64TrampolineWriter {
@@ -271,7 +270,7 @@ void X86X64Assembler::_bind(const Label& label) {
if (IntUtil::isInt8(patchedValue))
setByteAt(offset, static_cast<uint8_t>(patchedValue & 0xFF));
else
setError(kErrorAssemblerIllegalShortJump);
setError(kErrorIllegalDisplacement);
}
}
@@ -352,22 +351,27 @@ Error X86X64Assembler::embedLabel(const Label& op) {
// [asmjit::x86x64::Assembler - Align]
// ============================================================================
Error X86X64Assembler::_align(uint32_t m) {
Error X86X64Assembler::_align(uint32_t mode, uint32_t offset) {
if (_logger) {
_logger->logFormat(kLoggerStyleDirective,
"%s.align %u\n", _logger->getIndentation(), static_cast<unsigned int>(m));
"%s.align %u\n", _logger->getIndentation(), static_cast<unsigned int>(offset));
}
if (m <= 1 || !IntUtil::isPowerOf2(m) || m > 64)
if (offset <= 1 || !IntUtil::isPowerOf2(offset) || offset > 64)
return setError(kErrorInvalidArgument);
uint32_t i = static_cast<uint32_t>(IntUtil::deltaTo<size_t>(getOffset(), m));
uint32_t i = static_cast<uint32_t>(IntUtil::deltaTo<size_t>(getOffset(), offset));
if (i == 0)
return kErrorOk;
if (getRemainingSpace() < i)
ASMJIT_PROPAGATE_ERROR(_grow(i));
uint8_t* cursor = getCursor();
uint8_t alignPattern = 0xCC;
if (mode == kAlignCode) {
alignPattern = 0x90;
if (IntUtil::hasBit(_features, kCodeGenOptimizedAlign)) {
const CpuInfo* cpuInfo = static_cast<const CpuInfo*>(getRuntime()->getCpuInfo());
@@ -400,7 +404,9 @@ Error X86X64Assembler::_align(uint32_t m) {
const uint8_t* p;
uint32_t n;
if (cpuInfo->getVendorId() == kCpuVendorIntel && ((cpuInfo->getFamily() & 0x0F) == 0x06 || (cpuInfo->getFamily() & 0x0F) == 0x0F)) {
if (cpuInfo->getVendorId() == kCpuVendorIntel && (
(cpuInfo->getFamily() & 0x0F) == 0x06 ||
(cpuInfo->getFamily() & 0x0F) == 0x0F)) {
do {
switch (i) {
case 1: p = nop1; n = 1; break;
@@ -442,23 +448,11 @@ Error X86X64Assembler::_align(uint32_t m) {
} while (--n);
} while (i);
}
// Legacy NOPs, 0x90 with 0x66 prefix.
if (getArch() == kArchX86) {
while (i) {
switch (i) {
default: EMIT_BYTE(0x66); i--;
case 3: EMIT_BYTE(0x66); i--;
case 2: EMIT_BYTE(0x66); i--;
case 1: EMIT_BYTE(0x90); i--;
}
}
}
}
// Legacy NOPs, only 0x90.
while (i) {
EMIT_BYTE(0x90);
EMIT_BYTE(alignPattern);
i--;
}
@@ -898,7 +892,7 @@ static ASMJIT_INLINE uint32_t x86EncodeSib(uint32_t s, uint32_t i, uint32_t b) {
return (s << 6) + (i << 3) + b;
}
//! @internal
//! \internal
static const Operand::VRegOp x86PatchedHiRegs[4] = {
// --------------+---+--------------------------------+--------------+------+
// Operand | S | Register Code | OperandId |Unused|
@@ -1006,7 +1000,7 @@ _Prepare:
// Check if one or more register operand is one of BPL, SPL, SIL, DIL and
// force a REX prefix in such case.
if (x86IsGpbRegOp(o0)) {
if (X86Util::isGpbRegOp(*o0)) {
uint32_t index = static_cast<const X86Reg*>(o0)->getRegIndex();
if (static_cast<const X86Reg*>(o0)->isGpbLo()) {
opX |= (index >= 4) << kRexShift;
@@ -1017,7 +1011,7 @@ _Prepare:
}
}
if (x86IsGpbRegOp(o1)) {
if (X86Util::isGpbRegOp(*o1)) {
uint32_t index = static_cast<const X86Reg*>(o1)->getRegIndex();
if (static_cast<const X86Reg*>(o1)->isGpbLo()) {
opX |= (index >= 4) << kRexShift;
@@ -1509,6 +1503,37 @@ _Prepare:
}
break;
case kInstGroupX86Jecxz:
if (encoded == ENC_OPS(Reg, Label, None)) {
ASMJIT_ASSERT(static_cast<const X86Reg*>(o0)->getRegIndex() == kRegIndexCx);
if ((Arch == kArchX86 && o0->getSize() == 2) ||
Arch == kArchX64 && o0->getSize() == 4) {
EMIT_BYTE(0x67);
}
EMIT_BYTE(0xE3);
label = self->getLabelDataById(static_cast<const Label*>(o1)->getId());
if (label->offset != -1) {
// Bound label.
intptr_t offs = label->offset - (intptr_t)(cursor - self->_buffer) - 1;
if (!IntUtil::isInt8(offs))
goto _IllegalInst;
EMIT_BYTE(offs);
goto _EmitDone;
}
else {
// Non-bound label.
dispOffset = -1;
dispSize = 1;
relocId = -1;
goto _EmitDisplacement;
}
}
break;
case kInstGroupX86Jmp:
if (encoded == ENC_OPS(Reg, None, None)) {
rmReg = static_cast<const GpReg*>(o0)->getRegIndex();
@@ -3371,19 +3396,25 @@ _EmitAvxRvm:
// --------------------------------------------------------------------------
_IllegalInst:
self->setError(kErrorAssemblerIllegalInst);
self->setError(kErrorIllegalInst);
#if defined(ASMJIT_DEBUG)
assertIllegal = true;
#endif // ASMJIT_DEBUG
goto _EmitDone;
_IllegalAddr:
self->setError(kErrorAssemblerIllegalAddr);
self->setError(kErrorIllegalAddresing);
#if defined(ASMJIT_DEBUG)
assertIllegal = true;
#endif // ASMJIT_DEBUG
goto _EmitDone;
_IllegalDisp:
self->setError(kErrorIllegalDisplacement);
#if defined(ASMJIT_DEBUG)
assertIllegal = true;
#endif // ASMJIT_DEBUG
goto _EmitDone;
// --------------------------------------------------------------------------
// [Emit - X86]
@@ -3623,7 +3654,7 @@ _EmitSib:
// Indexing is invalid.
if (mIndex < kInvalidReg)
goto _IllegalAddr;
goto _IllegalDisp;
EMIT_BYTE(x86EncodeMod(0, opReg, 5));
dispOffset -= (4 + imLen);
@@ -4067,7 +4098,7 @@ _EmitDone:
_UnknownInst:
self->_comment = NULL;
return self->setError(kErrorAssemblerUnknownInst);
return self->setError(kErrorUnknownInst);
_GrowBuffer:
ASMJIT_PROPAGATE_ERROR(self->_grow(16));

File diff suppressed because it is too large Load Diff

View File

@@ -78,7 +78,7 @@ static Error X86X64Compiler_emitConstPool(X86X64Compiler* self,
if (label.getId() == kInvalidValue)
return kErrorOk;
self->align(static_cast<uint32_t>(pool.getAlignment()));
self->align(kAlignData, static_cast<uint32_t>(pool.getAlignment()));
self->bind(label);
EmbedNode* embedNode = self->embed(NULL, static_cast<uint32_t>(pool.getSize()));
@@ -656,8 +656,8 @@ Error X86X64Compiler::serialize(BaseAssembler& assembler) {
X86X64Context context(this);
Error error = kErrorOk;
BaseNode* node = _firstNode;
BaseNode* start;
Node* node = _firstNode;
Node* start;
// Find function and use the context to translate/emit.
do {

File diff suppressed because it is too large Load Diff

View File

@@ -78,10 +78,10 @@ void X86X64Context::reset() {
_clobberedRegs.reset();
_stackFrameCell = NULL;
_gaRegs[kRegClassGp] = IntUtil::bits(_baseRegsCount) & ~IntUtil::mask(kRegIndexSp);
_gaRegs[kRegClassFp] = IntUtil::bits(kRegCountFp);
_gaRegs[kRegClassMm] = IntUtil::bits(kRegCountMm);
_gaRegs[kRegClassXy] = IntUtil::bits(_baseRegsCount);
_gaRegs[kRegClassGp ] = IntUtil::bits(_baseRegsCount) & ~IntUtil::mask(kRegIndexSp);
_gaRegs[kRegClassFp ] = IntUtil::bits(kRegCountFp);
_gaRegs[kRegClassMm ] = IntUtil::bits(kRegCountMm);
_gaRegs[kRegClassXyz] = IntUtil::bits(_baseRegsCount);
_argBaseReg = kInvalidReg; // Used by patcher.
_varBaseReg = kInvalidReg; // Used by patcher.
@@ -142,6 +142,10 @@ static const X86X64SpecialInst x86SpecialInstDiv[] = {
{ kInvalidReg, kInvalidReg, kVarAttrInReg }
};
static const X86X64SpecialInst x86SpecialInstJecxz[] = {
{ kRegIndexCx, kInvalidReg, kVarAttrInReg }
};
static const X86X64SpecialInst x86SpecialInstMul[] = {
{ kInvalidReg, kRegIndexDx, kVarAttrOutReg },
{ kRegIndexAx, kRegIndexAx, kVarAttrInOutReg },
@@ -240,6 +244,9 @@ static ASMJIT_INLINE const X86X64SpecialInst* X86X64SpecialInst_get(uint32_t cod
case kInstDas:
return x86SpecialInstDaaDas;
case kInstJecxz:
return x86SpecialInstJecxz;
case kInstIdiv:
case kInstDiv:
return x86SpecialInstDiv;
@@ -384,7 +391,7 @@ void X86X64Context::emitLoad(VarData* vd, uint32_t regIndex, const char* reason)
X86X64Compiler* compiler = getCompiler();
Mem m = getVarMem(vd);
BaseNode* node = NULL;
Node* node = NULL;
bool comment = _emitComments;
switch (vd->getType()) {
@@ -465,7 +472,7 @@ void X86X64Context::emitSave(VarData* vd, uint32_t regIndex, const char* reason)
X86X64Compiler* compiler = getCompiler();
Mem m = getVarMem(vd);
BaseNode* node = NULL;
Node* node = NULL;
bool comment = _emitComments;
switch (vd->getType()) {
@@ -546,7 +553,7 @@ void X86X64Context::emitMove(VarData* vd, uint32_t toRegIndex, uint32_t fromRegI
X86X64Compiler* compiler = getCompiler();
BaseNode* node = NULL;
Node* node = NULL;
bool comment = _emitComments;
switch (vd->getType()) {
@@ -615,7 +622,7 @@ void X86X64Context::emitSwapGp(VarData* aVd, VarData* bVd, uint32_t aIndex, uint
X86X64Compiler* compiler = getCompiler();
BaseNode* node = NULL;
Node* node = NULL;
bool comment = _emitComments;
#if defined(ASMJIT_BUILD_X64)
@@ -1161,8 +1168,8 @@ _Move32:
case kVarTypeInt64:
case kVarTypeUInt64:
// Move to GPD register will clear the HI-DWORD of GPQ register in 64-bit
// mode.
// Move to Gpd register will clear also high DWORD of Gpq register in
// 64-bit mode.
if (imm.isUInt32())
goto _Move32Truncate;
@@ -1226,9 +1233,9 @@ static ASMJIT_INLINE void X86X64Context_checkStateVars(X86X64Context* self) {
}
void X86X64Context::_checkState() {
X86X64Context_checkStateVars<kRegClassGp>(this);
X86X64Context_checkStateVars<kRegClassMm>(this);
X86X64Context_checkStateVars<kRegClassXy>(this);
X86X64Context_checkStateVars<kRegClassGp >(this);
X86X64Context_checkStateVars<kRegClassMm >(this);
X86X64Context_checkStateVars<kRegClassXyz>(this);
}
#else
void X86X64Context::_checkState() {}
@@ -1270,9 +1277,9 @@ void X86X64Context::loadState(BaseVarState* src_) {
uint32_t vdCount = static_cast<uint32_t>(_contextVd.getLength());
// Load allocated variables.
X86X64Context_loadStateVars<kRegClassGp>(this, src);
X86X64Context_loadStateVars<kRegClassMm>(this, src);
X86X64Context_loadStateVars<kRegClassXy>(this, src);
X86X64Context_loadStateVars<kRegClassGp >(this, src);
X86X64Context_loadStateVars<kRegClassMm >(this, src);
X86X64Context_loadStateVars<kRegClassXyz>(this, src);
// Load masks.
cur->_occupied = src->_occupied;
@@ -1290,7 +1297,7 @@ void X86X64Context::loadState(BaseVarState* src_) {
vdArray[i]->setModified(false);
}
ASMJIT_CONTEXT_CHECK_STATE
ASMJIT_X86_CHECK_STATE
}
// ============================================================================
@@ -1463,9 +1470,9 @@ void X86X64Context::switchState(BaseVarState* src_) {
return;
// Switch variables.
X86X64Context_switchStateVars<kRegClassGp>(this, src);
X86X64Context_switchStateVars<kRegClassMm>(this, src);
X86X64Context_switchStateVars<kRegClassXy>(this, src);
X86X64Context_switchStateVars<kRegClassGp >(this, src);
X86X64Context_switchStateVars<kRegClassMm >(this, src);
X86X64Context_switchStateVars<kRegClassXyz>(this, src);
// Calculate changed state.
VarData** vdArray = _contextVd.getData();
@@ -1483,7 +1490,7 @@ void X86X64Context::switchState(BaseVarState* src_) {
}
}
ASMJIT_CONTEXT_CHECK_STATE
ASMJIT_X86_CHECK_STATE
}
// ============================================================================
@@ -1495,23 +1502,23 @@ void X86X64Context::intersectStates(BaseVarState* a_, BaseVarState* b_) {
VarState* bState = static_cast<VarState*>(b_);
// TODO: [COMPILER] Intersect states.
ASMJIT_CONTEXT_CHECK_STATE
ASMJIT_X86_CHECK_STATE
}
// ============================================================================
// [asmjit::x86x64::X86X64Context - GetJccFlow / GetOppositeJccFlow]
// ============================================================================
//! @internal
static ASMJIT_INLINE BaseNode* X86X64Context_getJccFlow(JumpNode* jNode) {
//! \internal
static ASMJIT_INLINE Node* X86X64Context_getJccFlow(JumpNode* jNode) {
if (jNode->isTaken())
return jNode->getTarget();
else
return jNode->getNext();
}
//! @internal
static ASMJIT_INLINE BaseNode* X86X64Context_getOppositeJccFlow(JumpNode* jNode) {
//! \internal
static ASMJIT_INLINE Node* X86X64Context_getOppositeJccFlow(JumpNode* jNode) {
if (jNode->isTaken())
return jNode->getNext();
else
@@ -1522,7 +1529,7 @@ static ASMJIT_INLINE BaseNode* X86X64Context_getOppositeJccFlow(JumpNode* jNode)
// [asmjit::x86x64::X86X64Context - SingleVarInst]
// ============================================================================
//! @internal
//! \internal
static void X86X64Context_prepareSingleVarInst(uint32_t code, VarAttr* va) {
switch (code) {
// - andn reg, reg ; Set all bits in reg to 0.
@@ -1555,11 +1562,11 @@ static void X86X64Context_prepareSingleVarInst(uint32_t code, VarAttr* va) {
// [asmjit::x86x64::X86X64Context - Helpers]
// ============================================================================
//! @internal
//! \internal
//!
//! Add unreachable-flow data to the unreachable flow list.
static ASMJIT_INLINE Error X86X64Context_addUnreachableNode(X86X64Context* self, BaseNode* node) {
PodList<BaseNode*>::Link* link = self->_baseZone.allocT<PodList<BaseNode*>::Link>();
static ASMJIT_INLINE Error X86X64Context_addUnreachableNode(X86X64Context* self, Node* node) {
PodList<Node*>::Link* link = self->_baseZone.allocT<PodList<Node*>::Link>();
if (link == NULL)
return self->setError(kErrorNoHeapMemory);
@@ -1569,11 +1576,11 @@ static ASMJIT_INLINE Error X86X64Context_addUnreachableNode(X86X64Context* self,
return kErrorOk;
}
//! @internal
//! \internal
//!
//! Add jump-flow data to the jcc flow list.
static ASMJIT_INLINE Error X86X64Context_addJccNode(X86X64Context* self, BaseNode* node) {
PodList<BaseNode*>::Link* link = self->_baseZone.allocT<PodList<BaseNode*>::Link>();
static ASMJIT_INLINE Error X86X64Context_addJccNode(X86X64Context* self, Node* node) {
PodList<Node*>::Link* link = self->_baseZone.allocT<PodList<Node*>::Link>();
if (link == NULL)
ASMJIT_PROPAGATE_ERROR(self->setError(kErrorNoHeapMemory));
@@ -1584,7 +1591,7 @@ static ASMJIT_INLINE Error X86X64Context_addJccNode(X86X64Context* self, BaseNod
return kErrorOk;
}
//! @internal
//! \internal
//!
//! Get mask of all registers actually used to pass function arguments.
static ASMJIT_INLINE RegMask X86X64Context_getUsedArgs(X86X64Context* self, X86X64CallNode* node, X86X64FuncDecl* decl) {
@@ -1813,7 +1820,7 @@ static ASMJIT_INLINE Error X86X64Context_insertSArgNode(
// [asmjit::x86x64::X86X64Context - Fetch]
// ============================================================================
//! @internal
//! \internal
//!
//! Prepare the given function `func`.
//!
@@ -1826,9 +1833,9 @@ Error X86X64Context::fetch() {
uint32_t arch = compiler->getArch();
BaseNode* node_ = func;
BaseNode* next = NULL;
BaseNode* stop = getStop();
Node* node_ = func;
Node* next = NULL;
Node* stop = getStop();
uint32_t groupId = 1;
uint32_t flowId = 0;
@@ -1836,7 +1843,7 @@ Error X86X64Context::fetch() {
VarAttr vaTmpList[80];
SArgData sArgList[80];
PodList<BaseNode*>::Link* jLink = NULL;
PodList<Node*>::Link* jLink = NULL;
// Function flags.
func->clearFuncFlags(
@@ -1913,7 +1920,7 @@ Error X86X64Context::fetch() {
else if (va->_outRegIndex != kInvalidReg) \
va->_allocableRegs = IntUtil::mask(va->_outRegIndex); \
else \
va->_allocableRegs &= ~inRegs._regs[class_]; \
va->_allocableRegs &= ~inRegs.get(class_); \
\
vd->_va = NULL; \
vi->getVa(index)[0] = va[0]; \
@@ -2001,10 +2008,10 @@ _NextGroup:
uint32_t remain[kRegClassCount];
HintNode* cur = node;
remain[kRegClassGp] = _baseRegsCount - 1 - func->hasFuncFlag(kFuncFlagIsNaked);
remain[kRegClassFp] = kRegCountFp;
remain[kRegClassMm] = kRegCountMm;
remain[kRegClassXy] = _baseRegsCount;
remain[kRegClassGp ] = _baseRegsCount - 1 - func->hasFuncFlag(kFuncFlagIsNaked);
remain[kRegClassFp ] = kRegCountFp;
remain[kRegClassMm ] = kRegCountMm;
remain[kRegClassXyz] = _baseRegsCount;
// Merge as many alloc-hints as possible.
for (;;) {
@@ -2020,14 +2027,14 @@ _NextGroup:
regMask = IntUtil::mask(regIndex);
if (va == NULL) {
if ((inRegs._regs[regClass] & regMask) != 0)
if (inRegs.has(regClass, regMask))
break;
if (remain[regClass] == 0)
break;
VI_ADD_VAR(vd, va, kVarAttrInReg, gaRegs[regClass]);
if (regMask != 0) {
inRegs._regs[regClass] ^= static_cast<uint16_t>(regMask);
inRegs.xor_(regClass, regMask);
va->setInRegs(regMask);
va->setInRegIndex(regIndex);
}
@@ -2035,10 +2042,10 @@ _NextGroup:
remain[regClass]--;
}
else if (regMask != 0) {
if ((inRegs._regs[regClass] & regMask) != 0 && va->getInRegs() != regMask)
if (inRegs.has(regClass, regMask) && va->getInRegs() != regMask)
break;
inRegs._regs[regClass] ^= static_cast<uint16_t>(va->getInRegs() | regMask);
inRegs.xor_(regClass, va->getInRegs() | regMask);
va->setInRegs(regMask);
va->setInRegIndex(regIndex);
}
@@ -2160,7 +2167,7 @@ _NextGroup:
if (static_cast<const X86Reg*>(op)->isGp())
c = kRegClassGp;
else
c = kRegClassXy;
c = kRegClassXyz;
if (inReg != kInvalidReg) {
uint32_t mask = IntUtil::mask(inReg);
@@ -2316,7 +2323,7 @@ _NextGroup:
if (node->isJmpOrJcc()) {
JumpNode* jNode = static_cast<JumpNode*>(node);
BaseNode* jNext = jNode->getNext();
Node* jNext = jNode->getNext();
TargetNode* jTarget = jNode->getTarget();
// If this jump is unconditional we put next node to unreachable node
@@ -2378,7 +2385,7 @@ _NextGroup:
// Overlapped function arguments.
if (vd->getVa() != NULL)
return compiler->setError(kErrorCompilerOverlappedArgs);
return compiler->setError(kErrorOverlappedArgs);
VI_ADD_VAR(vd, va, 0, 0);
uint32_t aType = arg.getVarType();
@@ -2575,10 +2582,10 @@ _NextGroup:
}
// Init clobbered.
clobberedRegs.set(kRegClassGp, IntUtil::bits(_baseRegsCount) & (~decl->getPreserved(kRegClassGp)));
clobberedRegs.set(kRegClassFp, IntUtil::bits(kRegCountFp ) );
clobberedRegs.set(kRegClassMm, IntUtil::bits(kRegCountMm ) & (~decl->getPreserved(kRegClassMm)));
clobberedRegs.set(kRegClassXy, IntUtil::bits(_baseRegsCount) & (~decl->getPreserved(kRegClassXy)));
clobberedRegs.set(kRegClassGp , IntUtil::bits(_baseRegsCount) & (~decl->getPreserved(kRegClassGp )));
clobberedRegs.set(kRegClassFp , IntUtil::bits(kRegCountFp ));
clobberedRegs.set(kRegClassMm , IntUtil::bits(kRegCountMm ) & (~decl->getPreserved(kRegClassMm )));
clobberedRegs.set(kRegClassXyz, IntUtil::bits(_baseRegsCount) & (~decl->getPreserved(kRegClassXyz)));
VI_END(node_);
break;
@@ -2606,7 +2613,7 @@ _NoMemory:
// [asmjit::x86x64::X86X64Context - Analyze]
// ============================================================================
//! @internal
//! \internal
struct LivenessTarget {
//! Previous target.
LivenessTarget* prev;
@@ -2620,7 +2627,7 @@ struct LivenessTarget {
Error X86X64Context::analyze() {
FuncNode* func = getFunc();
BaseNode* node = func->getEnd();
Node* node = func->getEnd();
JumpNode* from = NULL;
uint32_t bLen = static_cast<uint32_t>(
@@ -2905,8 +2912,8 @@ static bool X86X64Context_annotateInstruction(X86X64Context* self,
Error X86X64Context::annotate() {
FuncNode* func = getFunc();
BaseNode* node_ = func;
BaseNode* end = func->getEnd();
Node* node_ = func;
Node* end = func->getEnd();
Zone& sa = _compiler->_stringZone;
StringBuilderT<128> sb;
@@ -2958,7 +2965,7 @@ struct X86X64BaseAlloc {
ASMJIT_INLINE VarState* getState() const { return _context->getState(); }
//! Get the node.
ASMJIT_INLINE BaseNode* getNode() const { return _node; }
ASMJIT_INLINE Node* getNode() const { return _node; }
//! Get VarAttr list (all).
ASMJIT_INLINE VarAttr* getVaList() const { return _vaList[0]; }
@@ -2990,7 +2997,7 @@ struct X86X64BaseAlloc {
protected:
// Just to prevent calling these methods by X86X64Context::translate().
ASMJIT_INLINE void init(BaseNode* node, VarInst* vi);
ASMJIT_INLINE void init(Node* node, VarInst* vi);
ASMJIT_INLINE void cleanup();
// --------------------------------------------------------------------------
@@ -3013,7 +3020,7 @@ protected:
X86X64Compiler* _compiler;
//! Node.
BaseNode* _node;
Node* _node;
//! Variable instructions.
VarInst* _vi;
@@ -3033,7 +3040,7 @@ protected:
// [asmjit::x86x64::X86X64BaseAlloc - Init / Cleanup]
// ============================================================================
ASMJIT_INLINE void X86X64BaseAlloc::init(BaseNode* node, VarInst* vi) {
ASMJIT_INLINE void X86X64BaseAlloc::init(Node* node, VarInst* vi) {
_node = node;
_vi = vi;
@@ -3045,10 +3052,10 @@ ASMJIT_INLINE void X86X64BaseAlloc::init(BaseNode* node, VarInst* vi) {
// Setup the lists of variables.
{
VarAttr* va = vi->getVaList();
_vaList[kRegClassGp] = va;
_vaList[kRegClassFp] = va + vi->getVaStart(kRegClassFp);
_vaList[kRegClassMm] = va + vi->getVaStart(kRegClassMm);
_vaList[kRegClassXy] = va + vi->getVaStart(kRegClassXy);
_vaList[kRegClassGp ] = va;
_vaList[kRegClassFp ] = va + vi->getVaStart(kRegClassFp );
_vaList[kRegClassMm ] = va + vi->getVaStart(kRegClassMm );
_vaList[kRegClassXyz] = va + vi->getVaStart(kRegClassXyz);
}
// Setup counters.
@@ -3118,7 +3125,7 @@ ASMJIT_INLINE void X86X64BaseAlloc::unuseAfter() {
// [asmjit::x86x64::X86X64VarAlloc]
// ============================================================================
//! @internal
//! \internal
//!
//! Register allocator context (asm instructions).
struct X86X64VarAlloc : public X86X64BaseAlloc {
@@ -3133,7 +3140,7 @@ struct X86X64VarAlloc : public X86X64BaseAlloc {
// [Run]
// --------------------------------------------------------------------------
ASMJIT_INLINE Error run(BaseNode* node);
ASMJIT_INLINE Error run(Node* node);
// --------------------------------------------------------------------------
// [Init / Cleanup]
@@ -3142,7 +3149,7 @@ struct X86X64VarAlloc : public X86X64BaseAlloc {
protected:
// Just to prevent calling these methods by X86X64Context::translate().
ASMJIT_INLINE void init(BaseNode* node, VarInst* vi);
ASMJIT_INLINE void init(Node* node, VarInst* vi);
ASMJIT_INLINE void cleanup();
// --------------------------------------------------------------------------
@@ -3198,7 +3205,7 @@ protected:
// [asmjit::X86X64VarAlloc - Run]
// ============================================================================
ASMJIT_INLINE Error X86X64VarAlloc::run(BaseNode* node_) {
ASMJIT_INLINE Error X86X64VarAlloc::run(Node* node_) {
// Initialize.
VarInst* vi = node_->getVarInst<VarInst>();
if (vi == NULL)
@@ -3208,25 +3215,25 @@ ASMJIT_INLINE Error X86X64VarAlloc::run(BaseNode* node_) {
init(node_, vi);
// Unuse overwritten variables.
unuseBefore<kRegClassGp>();
unuseBefore<kRegClassMm>();
unuseBefore<kRegClassXy>();
unuseBefore<kRegClassGp >();
unuseBefore<kRegClassMm >();
unuseBefore<kRegClassXyz>();
// Plan the allocation. Planner assigns input/output registers for each
// variable and decides whether to allocate it in register or stack.
plan<kRegClassGp>();
plan<kRegClassMm>();
plan<kRegClassXy>();
plan<kRegClassGp >();
plan<kRegClassMm >();
plan<kRegClassXyz>();
// Spill all variables marked by plan().
spill<kRegClassGp>();
spill<kRegClassMm>();
spill<kRegClassXy>();
spill<kRegClassGp >();
spill<kRegClassMm >();
spill<kRegClassXyz>();
// Alloc all variables marked by plan().
alloc<kRegClassGp>();
alloc<kRegClassMm>();
alloc<kRegClassXy>();
alloc<kRegClassGp >();
alloc<kRegClassMm >();
alloc<kRegClassXyz>();
// Translate node operands.
if (node_->getType() == kNodeTypeInst) {
@@ -3271,9 +3278,9 @@ ASMJIT_INLINE Error X86X64VarAlloc::run(BaseNode* node_) {
}
// Mark variables as modified.
modified<kRegClassGp>();
modified<kRegClassMm>();
modified<kRegClassXy>();
modified<kRegClassGp >();
modified<kRegClassMm >();
modified<kRegClassXyz>();
// Cleanup; disconnect Vd->Va.
cleanup();
@@ -3283,9 +3290,9 @@ ASMJIT_INLINE Error X86X64VarAlloc::run(BaseNode* node_) {
_context->_clobberedRegs.add(vi->_clobberedRegs);
// Unuse.
unuseAfter<kRegClassGp>();
unuseAfter<kRegClassMm>();
unuseAfter<kRegClassXy>();
unuseAfter<kRegClassGp >();
unuseAfter<kRegClassMm >();
unuseAfter<kRegClassXyz>();
return kErrorOk;
}
@@ -3294,7 +3301,7 @@ ASMJIT_INLINE Error X86X64VarAlloc::run(BaseNode* node_) {
// [asmjit::x86x64::X86X64VarAlloc - Init / Cleanup]
// ============================================================================
ASMJIT_INLINE void X86X64VarAlloc::init(BaseNode* node, VarInst* vi) {
ASMJIT_INLINE void X86X64VarAlloc::init(Node* node, VarInst* vi) {
X86X64BaseAlloc::init(node, vi);
// These will block planner from assigning them during planning. Planner will
@@ -3663,7 +3670,7 @@ ASMJIT_INLINE uint32_t X86X64VarAlloc::guessAlloc(VarData* vd, uint32_t allocabl
uint32_t maxLookAhead = _compiler->getMaxLookAhead();
// Look ahead and calculate mask of special registers on both - input/output.
BaseNode* node = _node;
Node* node = _node;
for (i = 0; i < maxLookAhead; i++) {
// Stop on 'RetNode' and 'EndNode.
if (node->hasFlag(kNodeFlagIsRet))
@@ -3743,7 +3750,7 @@ ASMJIT_INLINE void X86X64VarAlloc::modified() {
// [asmjit::x86x64::X86X64CallAlloc]
// ============================================================================
//! @internal
//! \internal
//!
//! Register allocator context (function call).
struct X86X64CallAlloc : public X86X64BaseAlloc {
@@ -3858,33 +3865,33 @@ ASMJIT_INLINE Error X86X64CallAlloc::run(X86X64CallNode* node) {
// Plan register allocation. Planner is only able to assign one register per
// variable. If any variable is used multiple times it will be handled later.
plan<kRegClassGp>();
plan<kRegClassMm>();
plan<kRegClassXy>();
plan<kRegClassGp >();
plan<kRegClassMm >();
plan<kRegClassXyz>();
// Spill.
spill<kRegClassGp>();
spill<kRegClassMm>();
spill<kRegClassXy>();
spill<kRegClassGp >();
spill<kRegClassMm >();
spill<kRegClassXyz>();
// Alloc.
alloc<kRegClassGp>();
alloc<kRegClassMm>();
alloc<kRegClassXy>();
alloc<kRegClassGp >();
alloc<kRegClassMm >();
alloc<kRegClassXyz>();
// Unuse clobbered registers that are not used to pass function arguments and
// save variables used to pass function arguments that will be reused later on.
save<kRegClassGp>();
save<kRegClassMm>();
save<kRegClassXy>();
save<kRegClassGp >();
save<kRegClassMm >();
save<kRegClassXyz>();
// Allocate immediates in registers and on the stack.
allocImmsOnStack();
// Duplicate.
duplicate<kRegClassGp>();
duplicate<kRegClassMm>();
duplicate<kRegClassXy>();
duplicate<kRegClassGp >();
duplicate<kRegClassMm >();
duplicate<kRegClassXyz>();
// Translate call operand.
ASMJIT_PROPAGATE_ERROR(X86X64Context_translateOperands(_context, &node->_target, 1));
@@ -3899,17 +3906,17 @@ ASMJIT_INLINE Error X86X64CallAlloc::run(X86X64CallNode* node) {
}
// Clobber.
clobber<kRegClassGp>();
clobber<kRegClassMm>();
clobber<kRegClassXy>();
clobber<kRegClassGp >();
clobber<kRegClassMm >();
clobber<kRegClassXyz>();
// Return.
ret();
// Unuse.
unuseAfter<kRegClassGp>();
unuseAfter<kRegClassMm>();
unuseAfter<kRegClassXy>();
unuseAfter<kRegClassGp >();
unuseAfter<kRegClassMm >();
unuseAfter<kRegClassXyz>();
// Cleanup; disconnect Vd->Va.
cleanup();
@@ -4253,7 +4260,7 @@ ASMJIT_INLINE uint32_t X86X64CallAlloc::guessAlloc(VarData* vd, uint32_t allocab
uint32_t maxLookAhead = _compiler->getMaxLookAhead();
// Look ahead and calculate mask of special registers on both - input/output.
BaseNode* node = _node;
Node* node = _node;
for (i = 0; i < maxLookAhead; i++) {
// Stop on 'RetNode' and 'EndNode.
if (node->hasFlag(kNodeFlagIsRet))
@@ -4392,10 +4399,10 @@ ASMJIT_INLINE void X86X64CallAlloc::ret() {
_context->unuse<kRegClassMm>(vd);
_context->attach<kRegClassMm>(vd, regIndex, true);
break;
case kRegClassXy:
case kRegClassXyz:
if (vd->getRegIndex() != kInvalidReg)
_context->unuse<kRegClassXy>(vd);
_context->attach<kRegClassXy>(vd, regIndex, true);
_context->unuse<kRegClassXyz>(vd);
_context->attach<kRegClassXyz>(vd, regIndex, true);
break;
}
}
@@ -4405,7 +4412,7 @@ ASMJIT_INLINE void X86X64CallAlloc::ret() {
// [asmjit::x86x64::X86X64Context - TranslateOperands]
// ============================================================================
//! @internal
//! \internal
static Error X86X64Context_translateOperands(X86X64Context* self, Operand* opList, uint32_t opCount) {
X86X64Compiler* compiler = self->getCompiler();
const VarInfo* varInfo = _varInfo;
@@ -4460,7 +4467,7 @@ static Error X86X64Context_translateOperands(X86X64Context* self, Operand* opLis
// [asmjit::x86x64::X86X64Context - TranslatePrologEpilog]
// ============================================================================
//! @internal
//! \internal
static Error X86X64Context_initFunc(X86X64Context* self, X86X64FuncNode* func) {
X86X64Compiler* compiler = self->getCompiler();
X86X64FuncDecl* decl = func->getDecl();
@@ -4469,10 +4476,10 @@ static Error X86X64Context_initFunc(X86X64Context* self, X86X64FuncNode* func) {
uint32_t regSize = compiler->getRegSize();
// Setup "Save-Restore" registers.
func->_saveRestoreRegs.set(kRegClassGp, clobberedRegs.get(kRegClassGp) & decl->getPreserved(kRegClassGp));
func->_saveRestoreRegs.set(kRegClassFp, 0 );
func->_saveRestoreRegs.set(kRegClassMm, clobberedRegs.get(kRegClassMm) & decl->getPreserved(kRegClassMm));
func->_saveRestoreRegs.set(kRegClassXy, clobberedRegs.get(kRegClassXy) & decl->getPreserved(kRegClassXy));
func->_saveRestoreRegs.set(kRegClassGp , clobberedRegs.get(kRegClassGp ) & decl->getPreserved(kRegClassGp ));
func->_saveRestoreRegs.set(kRegClassFp , 0);
func->_saveRestoreRegs.set(kRegClassMm , clobberedRegs.get(kRegClassMm ) & decl->getPreserved(kRegClassMm ));
func->_saveRestoreRegs.set(kRegClassXyz, clobberedRegs.get(kRegClassXyz) & decl->getPreserved(kRegClassXyz));
ASMJIT_ASSERT(!func->_saveRestoreRegs.has(kRegClassGp, IntUtil::mask(kRegIndexSp)));
@@ -4484,7 +4491,7 @@ static Error X86X64Context_initFunc(X86X64Context* self, X86X64FuncNode* func) {
// Require 16-byte alignment if 8-byte vars are used.
if (self->_mem8ByteVarsUsed)
requiredStackAlignment = 16;
else if (func->_saveRestoreRegs.get(kRegClassMm) || func->_saveRestoreRegs.get(kRegClassXy))
else if (func->_saveRestoreRegs.get(kRegClassMm) || func->_saveRestoreRegs.get(kRegClassXyz))
requiredStackAlignment = 16;
else if (IntUtil::inInterval<uint32_t>(func->getRequiredStackAlignment(), 8, 16))
requiredStackAlignment = 16;
@@ -4580,9 +4587,9 @@ static Error X86X64Context_initFunc(X86X64Context* self, X86X64FuncNode* func) {
// Setup stack size used to save preserved registers.
{
uint32_t memGpSize = IntUtil::bitCount(func->_saveRestoreRegs.get(kRegClassGp)) * regSize;
uint32_t memMmSize = IntUtil::bitCount(func->_saveRestoreRegs.get(kRegClassMm)) * 8;
uint32_t memXmmSize = IntUtil::bitCount(func->_saveRestoreRegs.get(kRegClassXy)) * 16;
uint32_t memGpSize = IntUtil::bitCount(func->_saveRestoreRegs.get(kRegClassGp )) * regSize;
uint32_t memMmSize = IntUtil::bitCount(func->_saveRestoreRegs.get(kRegClassMm )) * 8;
uint32_t memXmmSize = IntUtil::bitCount(func->_saveRestoreRegs.get(kRegClassXyz)) * 16;
if (func->hasFuncFlag(kFuncFlagPushPop)) {
func->_pushPopStackSize = memGpSize;
@@ -4663,10 +4670,10 @@ static Error X86X64Context_initFunc(X86X64Context* self, X86X64FuncNode* func) {
return kErrorOk;
}
//! @internal
static Error X86X64Context_patchFuncMem(X86X64Context* self, X86X64FuncNode* func, BaseNode* stop) {
//! \internal
static Error X86X64Context_patchFuncMem(X86X64Context* self, X86X64FuncNode* func, Node* stop) {
X86X64Compiler* compiler = self->getCompiler();
BaseNode* node = func;
Node* node = func;
do {
if (node->getType() == kNodeTypeInst) {
@@ -4702,7 +4709,7 @@ static Error X86X64Context_patchFuncMem(X86X64Context* self, X86X64FuncNode* fun
return kErrorOk;
}
//! @internal
//! \internal
static Error X86X64Context_translatePrologEpilog(X86X64Context* self, X86X64FuncNode* func) {
X86X64Compiler* compiler = self->getCompiler();
X86X64FuncDecl* decl = func->getDecl();
@@ -4733,9 +4740,9 @@ static Error X86X64Context_translatePrologEpilog(X86X64Context* self, X86X64Func
}
uint32_t i, mask;
uint32_t regsGp = func->getSaveRestoreRegs(kRegClassGp);
uint32_t regsMm = func->getSaveRestoreRegs(kRegClassMm);
uint32_t regsXmm = func->getSaveRestoreRegs(kRegClassXy);
uint32_t regsGp = func->getSaveRestoreRegs(kRegClassGp );
uint32_t regsMm = func->getSaveRestoreRegs(kRegClassMm );
uint32_t regsXmm = func->getSaveRestoreRegs(kRegClassXyz);
bool earlyPushPop = false;
bool useLeaEpilog = false;
@@ -4966,10 +4973,10 @@ static Error X86X64Context_translatePrologEpilog(X86X64Context* self, X86X64Func
// [asmjit::x86x64::X86X64Context - Translate - Jump]
// ============================================================================
//! @internal
//! \internal
static void X86X64Context_translateJump(X86X64Context* self, JumpNode* jNode, TargetNode* jTarget) {
X86X64Compiler* compiler = self->getCompiler();
BaseNode* extNode = self->getExtraBlock();
Node* extNode = self->getExtraBlock();
// TODO: [COMPILER] State Change.
compiler->_setCursor(extNode);
@@ -5003,7 +5010,7 @@ static void X86X64Context_translateJump(X86X64Context* self, JumpNode* jNode, Ta
// ============================================================================
static Error X86X64Context_translateRet(X86X64Context* self, RetNode* rNode, TargetNode* exitTarget) {
BaseNode* node = rNode->getNext();
Node* node = rNode->getNext();
while (node != NULL) {
switch (node->getType()) {
@@ -5061,11 +5068,11 @@ Error X86X64Context::translate() {
X86X64CallAlloc cAlloc(this);
// Flow.
BaseNode* node_ = func;
BaseNode* next = NULL;
BaseNode* stop = getStop();
Node* node_ = func;
Node* next = NULL;
Node* stop = getStop();
PodList<BaseNode*>::Link* jLink = _jccList.getFirst();
PodList<Node*>::Link* jLink = _jccList.getFirst();
for (;;) {
while (node_->isTranslated()) {
@@ -5084,7 +5091,7 @@ _NextGroup:
node_ = jLink->getValue();
jLink = jLink->getNext();
BaseNode* jFlow = X86X64Context_getOppositeJccFlow(static_cast<JumpNode*>(node_));
Node* jFlow = X86X64Context_getOppositeJccFlow(static_cast<JumpNode*>(node_));
loadState(node_->getState());
if (jFlow->getState()) {
@@ -5180,7 +5187,7 @@ _NextGroup:
}
}
else {
BaseNode* jNext = node->getNext();
Node* jNext = node->getNext();
if (jTarget->isTranslated()) {
if (jNext->isTranslated()) {
@@ -5245,9 +5252,9 @@ _NextGroup:
uint32_t regIndex = va->getOutRegIndex();
if (regIndex != kInvalidReg && (va->getFlags() & kVarAttrOutConv) == 0) {
switch (vd->getClass()) {
case kRegClassGp: attach<kRegClassGp>(vd, regIndex, true); break;
case kRegClassMm: attach<kRegClassMm>(vd, regIndex, true); break;
case kRegClassXy: attach<kRegClassXy>(vd, regIndex, true); break;
case kRegClassGp : attach<kRegClassGp >(vd, regIndex, true); break;
case kRegClassMm : attach<kRegClassMm >(vd, regIndex, true); break;
case kRegClassXyz: attach<kRegClassXyz>(vd, regIndex, true); break;
}
}
else if (va->hasFlag(kVarAttrOutConv)) {
@@ -5294,8 +5301,8 @@ _Done:
// ============================================================================
template<int LoggingEnabled>
static ASMJIT_INLINE Error X86X64Context_serialize(X86X64Context* self, X86X64Assembler* assembler, BaseNode* start, BaseNode* stop) {
BaseNode* node_ = start;
static ASMJIT_INLINE Error X86X64Context_serialize(X86X64Context* self, X86X64Assembler* assembler, Node* start, Node* stop) {
Node* node_ = start;
StringBuilder& sb = self->_stringBuilder;
Logger* logger;
@@ -5365,7 +5372,7 @@ static ASMJIT_INLINE Error X86X64Context_serialize(X86X64Context* self, X86X64As
switch (node_->getType()) {
case kNodeTypeAlign: {
AlignNode* node = static_cast<AlignNode*>(node_);
assembler->align(node->getSize());
assembler->align(node->getMode(), node->getOffset());
break;
}
@@ -5562,7 +5569,7 @@ static ASMJIT_INLINE Error X86X64Context_serialize(X86X64Context* self, X86X64As
return kErrorOk;
}
Error X86X64Context::serialize(BaseAssembler* assembler, BaseNode* start, BaseNode* stop) {
Error X86X64Context::serialize(BaseAssembler* assembler, Node* start, Node* stop) {
if (!assembler->hasLogger())
return X86X64Context_serialize<0>(this, static_cast<X86X64Assembler*>(assembler), start, stop);
else

View File

@@ -14,7 +14,6 @@
#include "../base/intutil.h"
#include "../x86/x86assembler.h"
#include "../x86/x86compiler.h"
#include "../x86/x86defs.h"
// [Api-Begin]
#include "../apibegin.h"
@@ -22,14 +21,20 @@
namespace asmjit {
namespace x86x64 {
//! @addtogroup asmjit_x86x64_codegen
//! @{
// ============================================================================
// [asmjit::Context]
// ============================================================================
//! @internal
#if defined(ASMJIT_DEBUG)
# define ASMJIT_X86_CHECK_STATE _checkState();
#else
# define ASMJIT_X86_CHECK_STATE
#endif // ASMJIT_DEBUG
//! \addtogroup asmjit_x86x64_tree
//! \{
//! \internal
//!
//! Compiler context is used by `X86X64Compiler`.
//!
@@ -110,14 +115,8 @@ struct X86X64Context : public BaseContext {
void _checkState();
#if defined(ASMJIT_DEBUG)
#define ASMJIT_CONTEXT_CHECK_STATE _checkState();
#else
#define ASMJIT_CONTEXT_CHECK_STATE
#endif // ASMJIT_DEBUG
ASMJIT_INLINE uint32_t getRegsCount(uint32_t c) const {
if (c == kRegClassGp || c == kRegClassXy)
if (c == kRegClassGp || c == kRegClassXyz)
return _baseRegsCount;
else
return 8;
@@ -154,7 +153,7 @@ struct X86X64Context : public BaseContext {
_x86State._occupied.add(C, regMask);
_x86State._modified.add(C, static_cast<uint32_t>(modified) << regIndex);
ASMJIT_CONTEXT_CHECK_STATE
ASMJIT_X86_CHECK_STATE
}
//! Detach.
@@ -178,7 +177,7 @@ struct X86X64Context : public BaseContext {
_x86State._occupied.del(C, regMask);
_x86State._modified.del(C, regMask);
ASMJIT_CONTEXT_CHECK_STATE
ASMJIT_X86_CHECK_STATE
}
// --------------------------------------------------------------------------
@@ -206,7 +205,7 @@ struct X86X64Context : public BaseContext {
_x86State._occupied.xor_(C, bothRegMask);
_x86State._modified.xor_(C, bothRegMask & -static_cast<int32_t>(vd->isModified()));
ASMJIT_CONTEXT_CHECK_STATE
ASMJIT_X86_CHECK_STATE
}
// --------------------------------------------------------------------------
@@ -227,7 +226,7 @@ struct X86X64Context : public BaseContext {
emitLoad(vd, regIndex, "Load");
attach<C>(vd, regIndex, false);
ASMJIT_CONTEXT_CHECK_STATE
ASMJIT_X86_CHECK_STATE
}
//! Save.
@@ -247,7 +246,7 @@ struct X86X64Context : public BaseContext {
vd->setModified(false);
_x86State._modified.del(C, regMask);
ASMJIT_CONTEXT_CHECK_STATE
ASMJIT_X86_CHECK_STATE
}
// --------------------------------------------------------------------------
@@ -270,7 +269,7 @@ struct X86X64Context : public BaseContext {
rebase<C>(vd, regIndex, oldIndex);
}
ASMJIT_CONTEXT_CHECK_STATE
ASMJIT_X86_CHECK_STATE
}
//! Swap two registers
@@ -301,7 +300,7 @@ struct X86X64Context : public BaseContext {
uint32_t m = aVd->isModified() ^ bVd->isModified();
_x86State._modified.xor_(kRegClassGp, (m << aIndex) | (m << bIndex));
ASMJIT_CONTEXT_CHECK_STATE
ASMJIT_X86_CHECK_STATE
}
// --------------------------------------------------------------------------
@@ -332,7 +331,7 @@ struct X86X64Context : public BaseContext {
regMask ^= IntUtil::mask(oldRegIndex);
}
else {
ASMJIT_CONTEXT_CHECK_STATE
ASMJIT_X86_CHECK_STATE
return;
}
@@ -343,7 +342,7 @@ struct X86X64Context : public BaseContext {
_x86State._occupied.xor_(C, regMask);
_x86State._modified.xor_(C, regMask & -static_cast<int32_t>(vd->isModified()));
ASMJIT_CONTEXT_CHECK_STATE
ASMJIT_X86_CHECK_STATE
}
//! Spill.
@@ -354,7 +353,7 @@ struct X86X64Context : public BaseContext {
ASMJIT_ASSERT(vd->getClass() == C);
if (vd->getState() != kVarStateReg) {
ASMJIT_CONTEXT_CHECK_STATE
ASMJIT_X86_CHECK_STATE
return;
}
@@ -367,7 +366,7 @@ struct X86X64Context : public BaseContext {
emitSave(vd, regIndex, "Spill");
detach<C>(vd, regIndex, kVarStateMem);
ASMJIT_CONTEXT_CHECK_STATE
ASMJIT_X86_CHECK_STATE
}
// --------------------------------------------------------------------------
@@ -384,7 +383,7 @@ struct X86X64Context : public BaseContext {
vd->setModified(true);
_x86State._modified.add(C, regMask);
ASMJIT_CONTEXT_CHECK_STATE
ASMJIT_X86_CHECK_STATE
}
// --------------------------------------------------------------------------
@@ -406,7 +405,7 @@ struct X86X64Context : public BaseContext {
else
vd->setState(vState);
ASMJIT_CONTEXT_CHECK_STATE
ASMJIT_X86_CHECK_STATE
}
// --------------------------------------------------------------------------
@@ -459,7 +458,7 @@ struct X86X64Context : public BaseContext {
// [Serialize]
// --------------------------------------------------------------------------
virtual Error serialize(BaseAssembler* assembler, BaseNode* start, BaseNode* stop);
virtual Error serialize(BaseAssembler* assembler, Node* start, Node* stop);
// --------------------------------------------------------------------------
// [Members]
@@ -507,7 +506,7 @@ struct X86X64Context : public BaseContext {
StringBuilderT<256> _stringBuilder;
};
//! @}
//! \}
} // x86x64 namespace
} // asmjit namespace

View File

@@ -37,15 +37,11 @@ struct CpuVendor {
};
static const CpuVendor cpuVendorTable[] = {
{ kCpuVendorAmd , { 'A', 'M', 'D', 'i', 's', 'b', 'e', 't', 't', 'e', 'r', '!' } },
{ kCpuVendorAmd , { 'A', 'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'A', 'M', 'D' } },
{ kCpuVendorVia , { 'C', 'e', 'n', 't', 'a', 'u', 'r', 'H', 'a', 'u', 'l', 's' } },
{ kCpuVendorNSM , { 'C', 'y', 'r', 'i', 'x', 'I', 'n', 's', 't', 'e', 'a', 'd' } },
{ kCpuVendorIntel , { 'G', 'e', 'n', 'u', 'i', 'n', 'e', 'I', 'n', 't', 'e', 'l' } },
{ kCpuVendorTransmeta, { 'G', 'e', 'n', 'u', 'i', 'n', 'e', 'T', 'M', 'x', '8', '6' } },
{ kCpuVendorNSM , { 'G', 'e', 'o', 'd', 'e', ' ', 'b', 'y', ' ', 'N', 'S', 'C' } },
{ kCpuVendorTransmeta, { 'T', 'r', 'a', 'n', 's', 'm', 'e', 't', 'a', 'C', 'P', 'U' } },
{ kCpuVendorVia , { 'V', 'I', 'A', 0 , 'V', 'I', 'A', 0 , 'V', 'I', 'A', 0 } }
{ kCpuVendorAmd , { 'A', 'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'A', 'M', 'D' } },
{ kCpuVendorAmd , { 'A', 'M', 'D', 'i', 's', 'b', 'e', 't', 't', 'e', 'r', '!' } },
{ kCpuVendorVia , { 'V', 'I', 'A', 0 , 'V', 'I', 'A', 0 , 'V', 'I', 'A', 0 } },
{ kCpuVendorVia , { 'C', 'e', 'n', 't', 'a', 'u', 'r', 'H', 'a', 'u', 'l', 's' } }
};
static ASMJIT_INLINE bool cpuVendorEq(const CpuVendor& info, const char* vendorString) {
@@ -162,7 +158,7 @@ void CpuUtil::detect(CpuInfo* cpuInfo) {
::memcpy(cpuInfo->_vendorString + 4, &regs.edx, 4);
::memcpy(cpuInfo->_vendorString + 8, &regs.ecx, 4);
for (i = 0; i < 3; i++) {
for (i = 0; i < ASMJIT_ARRAY_SIZE(cpuVendorTable); i++) {
if (cpuVendorEq(cpuVendorTable[i], cpuInfo->_vendorString)) {
cpuInfo->_vendorId = cpuVendorTable[i].id;
break;

View File

@@ -10,7 +10,6 @@
// [Dependencies - AsmJit]
#include "../base/cpuinfo.h"
#include "../base/defs.h"
// [Api-Begin]
#include "../apibegin.h"
@@ -18,15 +17,15 @@
namespace asmjit {
namespace x86x64 {
//! @addtogroup asmjit_x86x64_cpu_info
//! @{
// ============================================================================
// [Forward Declarations]
// ============================================================================
struct CpuInfo;
//! \addtogroup asmjit_x86x64_general
//! \{
// ============================================================================
// [asmjit::x86x64::kCpuFeature]
// ============================================================================
@@ -221,7 +220,7 @@ struct CpuInfo : public BaseCpuInfo {
uint32_t _maxLogicalProcessors;
};
//! @}
//! \}
} // x86x64 namespace
} // asmjit namespace

View File

@@ -15,8 +15,8 @@
#include "../base/globals.h"
#include "../base/intutil.h"
#include "../base/string.h"
#include "../x86/x86defs.h"
#include "../x86/x86func.h"
#include "../x86/x86operand.h"
// [Api-Begin]
#include "../apibegin.h"
@@ -46,6 +46,13 @@ static ASMJIT_INLINE uint32_t x86ArgTypeToXmmType(uint32_t aType) {
return aType;
}
//! Get an architecture from calling convention.
//!
//! Returns `kArchX86` or `kArchX64` depending on `conv`.
static ASMJIT_INLINE uint32_t x86GetArchFromCConv(uint32_t conv) {
return IntUtil::inInterval<uint32_t>(conv, kFuncConvX64W, kFuncConvX64U) ? kArchX64 : kArchX86;
}
// ============================================================================
// [asmjit::X86X64FuncDecl - SetPrototype]
// ============================================================================
@@ -147,44 +154,44 @@ static uint32_t X86X64FuncDecl_initConv(X86X64FuncDecl* self, uint32_t arch, uin
case kFuncConvX64W:
self->_spillZoneSize = 32;
self->_passed.set(kRegClassGp, IntUtil::mask(R(Cx), R(Dx), R(R8), R(R9)));
self->_passed.set(kRegClassGp, IntUtil::mask(R(Cx), R(Dx), 8, 9));
self->_passedOrderGp[0] = R(Cx);
self->_passedOrderGp[1] = R(Dx);
self->_passedOrderGp[2] = R(R8);
self->_passedOrderGp[3] = R(R9);
self->_passedOrderGp[2] = 8;
self->_passedOrderGp[3] = 9;
self->_passed.set(kRegClassXy, IntUtil::mask(R(Xmm0), R(Xmm1), R(Xmm2), R(Xmm3)));
self->_passedOrderXmm[0] = R(Xmm0);
self->_passedOrderXmm[1] = R(Xmm1);
self->_passedOrderXmm[2] = R(Xmm2);
self->_passedOrderXmm[3] = R(Xmm3);
self->_passed.set(kRegClassXyz, IntUtil::mask(0, 1, 2, 3));
self->_passedOrderXmm[0] = 0;
self->_passedOrderXmm[1] = 1;
self->_passedOrderXmm[2] = 2;
self->_passedOrderXmm[3] = 3;
self->_preserved.set(kRegClassGp, IntUtil::mask(R(Bx), R(Sp), R(Bp), R(Si), R(Di), R(R12), R(R13), R(R14), R(R15)));
self->_preserved.set(kRegClassXy, IntUtil::mask(R(Xmm6), R(Xmm7), R(Xmm8), R(Xmm9), R(Xmm10), R(Xmm11), R(Xmm12), R(Xmm13), R(Xmm14), R(Xmm15)));
self->_preserved.set(kRegClassGp , IntUtil::mask(R(Bx), R(Sp), R(Bp), R(Si), R(Di), 12, 13, 14, 15));
self->_preserved.set(kRegClassXyz, IntUtil::mask(6, 7, 8, 9, 10, 11, 12, 13, 14, 15));
break;
case kFuncConvX64U:
self->_redZoneSize = 128;
self->_passed.set(kRegClassGp, IntUtil::mask(R(Di), R(Si), R(Dx), R(Cx), R(R8), R(R9)));
self->_passed.set(kRegClassGp, IntUtil::mask(R(Di), R(Si), R(Dx), R(Cx), 8, 9));
self->_passedOrderGp[0] = R(Di);
self->_passedOrderGp[1] = R(Si);
self->_passedOrderGp[2] = R(Dx);
self->_passedOrderGp[3] = R(Cx);
self->_passedOrderGp[4] = R(R8);
self->_passedOrderGp[5] = R(R9);
self->_passedOrderGp[4] = 8;
self->_passedOrderGp[5] = 9;
self->_passed.set(kRegClassXy, IntUtil::mask(R(Xmm0), R(Xmm1), R(Xmm2), R(Xmm3), R(Xmm4), R(Xmm5), R(Xmm6), R(Xmm7)));
self->_passedOrderXmm[0] = R(Xmm0);
self->_passedOrderXmm[1] = R(Xmm1);
self->_passedOrderXmm[2] = R(Xmm2);
self->_passedOrderXmm[3] = R(Xmm3);
self->_passedOrderXmm[4] = R(Xmm4);
self->_passedOrderXmm[5] = R(Xmm5);
self->_passedOrderXmm[6] = R(Xmm6);
self->_passedOrderXmm[7] = R(Xmm7);
self->_passed.set(kRegClassXyz, IntUtil::mask(0, 1, 2, 3, 4, 5, 6, 7));
self->_passedOrderXmm[0] = 0;
self->_passedOrderXmm[1] = 1;
self->_passedOrderXmm[2] = 2;
self->_passedOrderXmm[3] = 3;
self->_passedOrderXmm[4] = 4;
self->_passedOrderXmm[5] = 5;
self->_passedOrderXmm[6] = 6;
self->_passedOrderXmm[7] = 7;
self->_preserved.set(kRegClassGp, IntUtil::mask(R(Bx), R(Sp), R(Bp), R(R12), R(R13), R(R14), R(R15)));
self->_preserved.set(kRegClassGp, IntUtil::mask(R(Bx), R(Sp), R(Bp), 12, 13, 14, 15));
break;
default:
@@ -271,18 +278,18 @@ static Error X86X64FuncDecl_initFunc(X86X64FuncDecl* self, uint32_t arch,
case kVarTypeMm:
self->_retCount = 1;
self->_retList[0]._varType = static_cast<uint8_t>(ret);
self->_retList[0]._regIndex = kRegIndexMm0;
self->_retList[0]._regIndex = 0;
break;
case kVarTypeFp32:
self->_retCount = 1;
if (arch == kArchX86) {
self->_retList[0]._varType = kVarTypeFp32;
self->_retList[0]._regIndex = kRegIndexFp0;
self->_retList[0]._regIndex = 0;
}
else {
self->_retList[0]._varType = kVarTypeXmmSs;
self->_retList[0]._regIndex = kRegIndexXmm0;
self->_retList[0]._regIndex = 0;
}
break;
@@ -290,11 +297,11 @@ static Error X86X64FuncDecl_initFunc(X86X64FuncDecl* self, uint32_t arch,
self->_retCount = 1;
if (arch == kArchX86) {
self->_retList[0]._varType = kVarTypeFp64;
self->_retList[0]._regIndex = kRegIndexFp0;
self->_retList[0]._regIndex = 0;
}
else {
self->_retList[0]._varType = kVarTypeXmmSd;
self->_retList[0]._regIndex = kRegIndexXmm0;
self->_retList[0]._regIndex = 0;
break;
}
break;
@@ -306,7 +313,7 @@ static Error X86X64FuncDecl_initFunc(X86X64FuncDecl* self, uint32_t arch,
case kVarTypeXmmPd:
self->_retCount = 1;
self->_retList[0]._varType = static_cast<uint8_t>(ret);
self->_retList[0]._regIndex = kRegIndexXmm0;
self->_retList[0]._regIndex = 0;
break;
}
}
@@ -381,7 +388,7 @@ static Error X86X64FuncDecl_initFunc(X86X64FuncDecl* self, uint32_t arch,
if (x86ArgIsFp(varType) && i < ASMJIT_ARRAY_SIZE(self->_passedOrderXmm)) {
arg._varType = static_cast<uint8_t>(x86ArgTypeToXmmType(varType));
arg._regIndex = self->_passedOrderXmm[i];
self->_used.add(kRegClassXy, IntUtil::mask(arg.getRegIndex()));
self->_used.add(kRegClassXyz, IntUtil::mask(arg.getRegIndex()));
}
}
@@ -430,7 +437,7 @@ static Error X86X64FuncDecl_initFunc(X86X64FuncDecl* self, uint32_t arch,
if (x86ArgIsFp(varType)) {
arg._varType = static_cast<uint8_t>(x86ArgTypeToXmmType(varType));
arg._regIndex = self->_passedOrderXmm[xmmPos++];
self->_used.add(kRegClassXy, IntUtil::mask(arg.getRegIndex()));
self->_used.add(kRegClassXyz, IntUtil::mask(arg.getRegIndex()));
}
}

View File

@@ -9,9 +9,8 @@
#define _ASMJIT_X86_X86FUNC_H
// [Dependencies - AsmJit]
#include "../base/defs.h"
#include "../base/func.h"
#include "../x86/x86defs.h"
#include "../x86/x86util.h"
// [Api-Begin]
#include "../apibegin.h"
@@ -19,8 +18,8 @@
namespace asmjit {
namespace x86x64 {
//! @addtogroup asmjit_x86x64_codegen
//! @{
//! \addtogroup asmjit_x86x64_tree
//! \{
// ============================================================================
// [asmjit::x86x64::kFuncConv]
@@ -83,8 +82,8 @@ ASMJIT_ENUM(kFuncConv) {
//! - Caller.
//!
//! Return value:
//! - Integer types - RAX register.
//! - Floating points - XMM0 register.
//! - Integer types - Rax register.
//! - Floating points - Xmm0 register.
//!
//! Stack is always aligned by 16 bytes.
//!
@@ -109,8 +108,8 @@ ASMJIT_ENUM(kFuncConv) {
//! - Caller.
//!
//! Return value:
//! - Integer types - RAX register.
//! - Floating points - XMM0 register.
//! - Integer types - Rax register.
//! - Floating points - Xmm0 register.
//!
//! Stack is always aligned by 16 bytes.
kFuncConvX64U = 2,
@@ -165,7 +164,7 @@ ASMJIT_ENUM(kFuncConv) {
//! C++ class methods that have variable count of arguments uses different
//! calling convention called cdecl.
//!
//! @note This calling convention is always used by MSVC for class methods,
//! \note This calling convention is always used by MSVC for class methods,
//! it's implicit and there is no way how to override it.
kFuncConvMsThisCall = 5,
@@ -184,7 +183,7 @@ ASMJIT_ENUM(kFuncConv) {
//! - Integer types - EAX:EDX registers.
//! - Floating points - fp0 register.
//!
//! @note This calling convention differs to GCC one in stack cleaning
//! \note This calling convention differs to GCC one in stack cleaning
//! mechanism.
kFuncConvMsFastCall = 6,
@@ -203,7 +202,7 @@ ASMJIT_ENUM(kFuncConv) {
//! - Integer types - EAX:EDX registers.
//! - Floating points - fp0 register.
//!
//! @note Arguments on the stack are in left-to-right order that differs
//! \note Arguments on the stack are in left-to-right order that differs
//! to other fastcall conventions used in different compilers.
kFuncConvBorlandFastCall = 7,
@@ -222,7 +221,7 @@ ASMJIT_ENUM(kFuncConv) {
//! - Integer types - EAX:EDX registers.
//! - Floating points - fp0 register.
//!
//! @note This calling convention should be compatible with `kFuncConvMsFastCall`.
//! \note This calling convention should be compatible with `kFuncConvMsFastCall`.
kFuncConvGccFastCall = 8,
//! GCC specific regparm(1) convention.
@@ -273,7 +272,7 @@ ASMJIT_ENUM(kFuncConv) {
//! - Floating points - fp0 register.
kFuncConvGccRegParm3 = 11,
//! @internal
//! \internal
//!
//! Count of function calling conventions.
_kFuncConvCount = 12,
@@ -282,55 +281,51 @@ ASMJIT_ENUM(kFuncConv) {
// [Host]
// --------------------------------------------------------------------------
//! @def kFuncConvHost
#if defined(ASMJIT_DOCGEN)
//! Default calling convention for current platform / operating system.
kFuncConvHost = DependsOnHost,
//! @def kFuncConvHostCDecl
//! Default C calling convention based on current compiler's settings.
kFuncConvHostCDecl = DependsOnHost,
//! @def kFuncConvHostStdCall
//! Compatibility for `__stdcall` calling convention.
//!
//! @note This enumeration is always set to a value which is compatible with
//! \note This enumeration is always set to a value which is compatible with
//! current compilers __stdcall calling convention. In 64-bit mode the value
//! is compatible with `kFuncConvX64W` or `kFuncConvX64U`.
kFuncConvHostStdCall = DependsOnHost,
//! @def kFuncConvHostFastCall
//! Compatibility for `__fastcall` calling convention.
//!
//! @note This enumeration is always set to a value which is compatible with
//! \note This enumeration is always set to a value which is compatible with
//! current compilers `__fastcall` calling convention. In 64-bit mode the value
//! is compatible with `kFuncConvX64W` or `kFuncConvX64U`.
#if defined(ASMJIT_HOST_X86)
kFuncConvHostFastCall = DependsOnHost
#elif defined(ASMJIT_HOST_X86)
// X86.
kFuncConvHost = kFuncConvCDecl,
kFuncConvHostCDecl = kFuncConvCDecl,
kFuncConvHostStdCall = kFuncConvStdCall,
# if defined(_MSC_VER)
#if defined(_MSC_VER)
kFuncConvHostFastCall = kFuncConvMsFastCall
# elif defined(__GNUC__)
#elif defined(__GNUC__)
kFuncConvHostFastCall = kFuncConvGccFastCall
# elif defined(__BORLANDC__)
#elif defined(__BORLANDC__)
kFuncConvHostFastCall = kFuncConvBorlandFastCall
# else
# error "asmjit/x86/x86func.h - asmjit::kFuncConvHostFastCall not supported."
# endif
#else
# if defined(ASMJIT_OS_WINDOWS)
#error "kFuncConvHostFastCall not determined."
#endif
#else
// X64.
#if defined(ASMJIT_OS_WINDOWS)
kFuncConvHost = kFuncConvX64W,
# else
#else
kFuncConvHost = kFuncConvX64U,
# endif
#endif
kFuncConvHostCDecl = kFuncConvHost,
kFuncConvHostStdCall = kFuncConvHost,
kFuncConvHostFastCall = kFuncConvHost
#endif // ASMJIT_HOST
#endif
};
// ============================================================================
@@ -385,17 +380,6 @@ ASMJIT_ENUM(kFuncFlags) {
kFuncFlagLFence = 0x04000000
};
// ============================================================================
// [asmjit::x86x64::x86GetArchFromCConv]
// ============================================================================
//! Get architecture by a calling convention.
//!
//! Returns `kArchX86` or `kArchX64` depending on `conv`.
static ASMJIT_INLINE uint32_t x86GetArchFromCConv(uint32_t conv) {
return IntUtil::inInterval<uint32_t>(conv, kFuncConvX64W, kFuncConvX64U) ? kArchX64 : kArchX86;
}
// ============================================================================
// [asmjit::x86x64::X86X64FuncDecl]
// ============================================================================
@@ -418,7 +402,7 @@ struct X86X64FuncDecl : public FuncDecl {
//! Get used registers (mask).
//!
//! @note The result depends on the function calling convention AND the
//! \note The result depends on the function calling convention AND the
//! function prototype. Returned mask contains only registers actually used
//! to pass function arguments.
ASMJIT_INLINE uint32_t getUsed(uint32_t c) const {
@@ -427,7 +411,7 @@ struct X86X64FuncDecl : public FuncDecl {
//! Get passed registers (mask).
//!
//! @note The result depends on the function calling convention used; the
//! \note The result depends on the function calling convention used; the
//! prototype of the function doesn't affect the mask returned.
ASMJIT_INLINE uint32_t getPassed(uint32_t c) const {
return _passed.get(c);
@@ -435,7 +419,7 @@ struct X86X64FuncDecl : public FuncDecl {
//! Get preserved registers (mask).
//!
//! @note The result depends on the function calling convention used; the
//! \note The result depends on the function calling convention used; the
//! prototype of the function doesn't affect the mask returned.
ASMJIT_INLINE uint32_t getPreserved(uint32_t c) const {
return _preserved.get(c);
@@ -443,7 +427,7 @@ struct X86X64FuncDecl : public FuncDecl {
//! Get ther order of passed registers (Gp).
//!
//! @note The result depends on the function calling convention used; the
//! \note The result depends on the function calling convention used; the
//! prototype of the function doesn't affect the mask returned.
ASMJIT_INLINE const uint8_t* getPassedOrderGp() const {
return _passedOrderGp;
@@ -451,7 +435,7 @@ struct X86X64FuncDecl : public FuncDecl {
//! Get ther order of passed registers (Xmm).
//!
//! @note The result depends on the function calling convention used; the
//! \note The result depends on the function calling convention used; the
//! prototype of the function doesn't affect the mask returned.
ASMJIT_INLINE const uint8_t* getPassedOrderXmm() const {
return _passedOrderXmm;
@@ -465,7 +449,7 @@ struct X86X64FuncDecl : public FuncDecl {
//!
//! This will set function calling convention and setup arguments variables.
//!
//! @note This function will allocate variables, it can be called only once.
//! \note This function will allocate variables, it can be called only once.
ASMJIT_API Error setPrototype(uint32_t conv, const FuncPrototype& p);
// --------------------------------------------------------------------------
@@ -492,7 +476,7 @@ struct X86X64FuncDecl : public FuncDecl {
uint8_t _passedOrderXmm[8];
};
//! @}
//! \}
} // x86x64 namespace
} // asmjit namespace

File diff suppressed because it is too large Load Diff

1837
src/asmjit/x86/x86inst.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,338 @@
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Export]
#define ASMJIT_EXPORTS
// [Guard]
#include "../build.h"
#if defined(ASMJIT_BUILD_X86) || defined(ASMJIT_BUILD_X64)
// [Dependencies - AsmJit]
#include "../x86/x86operand.h"
// [Api-Begin]
#include "../apibegin.h"
namespace asmjit {
namespace x86x64 {
// ============================================================================
// [asmjit::x86x64::Variables]
// ============================================================================
#define C(_Class_) kRegClass##_Class_
#define D(_Desc_) kVarDesc##_Desc_
const VarInfo _varInfo[] = {
/* 00: kVarTypeInt8 */ { kRegTypeGpbLo, 1 , C(Gp) , 0 , "gpb" },
/* 01: kVarTypeUInt8 */ { kRegTypeGpbLo, 1 , C(Gp) , 0 , "gpb" },
/* 02: kVarTypeInt16 */ { kRegTypeGpw , 2 , C(Gp) , 0 , "gpw" },
/* 03: kVarTypeUInt16 */ { kRegTypeGpw , 2 , C(Gp) , 0 , "gpw" },
/* 04: kVarTypeInt32 */ { kRegTypeGpd , 4 , C(Gp) , 0 , "gpd" },
/* 05: kVarTypeUInt32 */ { kRegTypeGpd , 4 , C(Gp) , 0 , "gpd" },
/* 06: kVarTypeInt64 */ { kRegTypeGpq , 8 , C(Gp) , 0 , "gpq" },
/* 07: kVarTypeUInt64 */ { kRegTypeGpq , 8 , C(Gp) , 0 , "gpq" },
/* 08: kVarTypeIntPtr */ { 0 , 0 , C(Gp) , 0 , "" }, // Remapped.
/* 09: kVarTypeUIntPtr */ { 0 , 0 , C(Gp) , 0 , "" }, // Remapped.
/* 10: kVarTypeFp32 */ { kRegTypeFp , 4 , C(Fp) , D(Sp) , "fp" },
/* 11: kVarTypeFp64 */ { kRegTypeFp , 8 , C(Fp) , D(Dp) , "fp" },
/* 12: kVarTypeMm */ { kRegTypeMm , 8 , C(Mm) , 0 , "mm" },
/* 13: kVarTypeXmm */ { kRegTypeXmm , 16, C(Xyz), 0 , "xmm" },
/* 14: kVarTypeXmmSs */ { kRegTypeXmm , 4 , C(Xyz), D(Sp) , "xmm" },
/* 15: kVarTypeXmmPs */ { kRegTypeXmm , 16, C(Xyz), D(Sp) | D(Packed), "xmm" },
/* 16: kVarTypeXmmSd */ { kRegTypeXmm , 8 , C(Xyz), D(Dp) , "xmm" },
/* 17: kVarTypeXmmPd */ { kRegTypeXmm , 16, C(Xyz), D(Dp) | D(Packed), "xmm" },
/* 18: kVarTypeYmm */ { kRegTypeYmm , 32, C(Xyz), 0 , "ymm" },
/* 19: kVarTypeYmmPs */ { kRegTypeYmm , 32, C(Xyz), D(Sp) | D(Packed), "ymm" },
/* 20: kVarTypeYmmPd */ { kRegTypeYmm , 32, C(Xyz), D(Dp) | D(Packed), "ymm" }
};
#undef D
#undef C
// ============================================================================
// [asmjit::x86x64::Registers]
// ============================================================================
const GpReg noGpReg(kInvalidReg, kInvalidReg, 0);
const GpReg al(kRegTypeGpbLo, kRegIndexAx, 1);
const GpReg cl(kRegTypeGpbLo, kRegIndexCx, 1);
const GpReg dl(kRegTypeGpbLo, kRegIndexDx, 1);
const GpReg bl(kRegTypeGpbLo, kRegIndexBx, 1);
const GpReg spl(kRegTypeGpbLo, kRegIndexSp, 1);
const GpReg bpl(kRegTypeGpbLo, kRegIndexBp, 1);
const GpReg sil(kRegTypeGpbLo, kRegIndexSi, 1);
const GpReg dil(kRegTypeGpbLo, kRegIndexDi, 1);
const GpReg r8b(kRegTypeGpbLo, 8, 1);
const GpReg r9b(kRegTypeGpbLo, 9, 1);
const GpReg r10b(kRegTypeGpbLo, 10, 1);
const GpReg r11b(kRegTypeGpbLo, 11, 1);
const GpReg r12b(kRegTypeGpbLo, 12, 1);
const GpReg r13b(kRegTypeGpbLo, 13, 1);
const GpReg r14b(kRegTypeGpbLo, 14, 1);
const GpReg r15b(kRegTypeGpbLo, 15, 1);
const GpReg ah(kRegTypeGpbHi, kRegIndexAx, 1);
const GpReg ch(kRegTypeGpbHi, kRegIndexCx, 1);
const GpReg dh(kRegTypeGpbHi, kRegIndexDx, 1);
const GpReg bh(kRegTypeGpbHi, kRegIndexBx, 1);
const GpReg ax(kRegTypeGpw, kRegIndexAx, 2);
const GpReg cx(kRegTypeGpw, kRegIndexCx, 2);
const GpReg dx(kRegTypeGpw, kRegIndexDx, 2);
const GpReg bx(kRegTypeGpw, kRegIndexBx, 2);
const GpReg sp(kRegTypeGpw, kRegIndexSp, 2);
const GpReg bp(kRegTypeGpw, kRegIndexBp, 2);
const GpReg si(kRegTypeGpw, kRegIndexSi, 2);
const GpReg di(kRegTypeGpw, kRegIndexDi, 2);
const GpReg r8w(kRegTypeGpw, 8, 2);
const GpReg r9w(kRegTypeGpw, 9, 2);
const GpReg r10w(kRegTypeGpw, 10, 2);
const GpReg r11w(kRegTypeGpw, 11, 2);
const GpReg r12w(kRegTypeGpw, 12, 2);
const GpReg r13w(kRegTypeGpw, 13, 2);
const GpReg r14w(kRegTypeGpw, 14, 2);
const GpReg r15w(kRegTypeGpw, 15, 2);
const GpReg eax(kRegTypeGpd, kRegIndexAx, 4);
const GpReg ecx(kRegTypeGpd, kRegIndexCx, 4);
const GpReg edx(kRegTypeGpd, kRegIndexDx, 4);
const GpReg ebx(kRegTypeGpd, kRegIndexBx, 4);
const GpReg esp(kRegTypeGpd, kRegIndexSp, 4);
const GpReg ebp(kRegTypeGpd, kRegIndexBp, 4);
const GpReg esi(kRegTypeGpd, kRegIndexSi, 4);
const GpReg edi(kRegTypeGpd, kRegIndexDi, 4);
const GpReg r8d(kRegTypeGpd, 8, 4);
const GpReg r9d(kRegTypeGpd, 9, 4);
const GpReg r10d(kRegTypeGpd, 10, 4);
const GpReg r11d(kRegTypeGpd, 11, 4);
const GpReg r12d(kRegTypeGpd, 12, 4);
const GpReg r13d(kRegTypeGpd, 13, 4);
const GpReg r14d(kRegTypeGpd, 14, 4);
const GpReg r15d(kRegTypeGpd, 15, 4);
const GpReg rax(kRegTypeGpq, kRegIndexAx, 8);
const GpReg rcx(kRegTypeGpq, kRegIndexCx, 8);
const GpReg rdx(kRegTypeGpq, kRegIndexDx, 8);
const GpReg rbx(kRegTypeGpq, kRegIndexBx, 8);
const GpReg rsp(kRegTypeGpq, kRegIndexSp, 8);
const GpReg rbp(kRegTypeGpq, kRegIndexBp, 8);
const GpReg rsi(kRegTypeGpq, kRegIndexSi, 8);
const GpReg rdi(kRegTypeGpq, kRegIndexDi, 8);
const GpReg r8(kRegTypeGpq, 8, 8);
const GpReg r9(kRegTypeGpq, 9, 8);
const GpReg r10(kRegTypeGpq, 10, 8);
const GpReg r11(kRegTypeGpq, 11, 8);
const GpReg r12(kRegTypeGpq, 12, 8);
const GpReg r13(kRegTypeGpq, 13, 8);
const GpReg r14(kRegTypeGpq, 14, 8);
const GpReg r15(kRegTypeGpq, 15, 8);
const FpReg fp0(kRegTypeFp, 0, 10);
const FpReg fp1(kRegTypeFp, 1, 10);
const FpReg fp2(kRegTypeFp, 2, 10);
const FpReg fp3(kRegTypeFp, 3, 10);
const FpReg fp4(kRegTypeFp, 4, 10);
const FpReg fp5(kRegTypeFp, 5, 10);
const FpReg fp6(kRegTypeFp, 6, 10);
const FpReg fp7(kRegTypeFp, 7, 10);
const MmReg mm0(kRegTypeMm, 0, 8);
const MmReg mm1(kRegTypeMm, 1, 8);
const MmReg mm2(kRegTypeMm, 2, 8);
const MmReg mm3(kRegTypeMm, 3, 8);
const MmReg mm4(kRegTypeMm, 4, 8);
const MmReg mm5(kRegTypeMm, 5, 8);
const MmReg mm6(kRegTypeMm, 6, 8);
const MmReg mm7(kRegTypeMm, 7, 8);
const XmmReg xmm0(kRegTypeXmm, 0, 16);
const XmmReg xmm1(kRegTypeXmm, 1, 16);
const XmmReg xmm2(kRegTypeXmm, 2, 16);
const XmmReg xmm3(kRegTypeXmm, 3, 16);
const XmmReg xmm4(kRegTypeXmm, 4, 16);
const XmmReg xmm5(kRegTypeXmm, 5, 16);
const XmmReg xmm6(kRegTypeXmm, 6, 16);
const XmmReg xmm7(kRegTypeXmm, 7, 16);
const XmmReg xmm8(kRegTypeXmm, 8, 16);
const XmmReg xmm9(kRegTypeXmm, 9, 16);
const XmmReg xmm10(kRegTypeXmm, 10, 16);
const XmmReg xmm11(kRegTypeXmm, 11, 16);
const XmmReg xmm12(kRegTypeXmm, 12, 16);
const XmmReg xmm13(kRegTypeXmm, 13, 16);
const XmmReg xmm14(kRegTypeXmm, 14, 16);
const XmmReg xmm15(kRegTypeXmm, 15, 16);
const YmmReg ymm0(kRegTypeYmm, 0, 32);
const YmmReg ymm1(kRegTypeYmm, 1, 32);
const YmmReg ymm2(kRegTypeYmm, 2, 32);
const YmmReg ymm3(kRegTypeYmm, 3, 32);
const YmmReg ymm4(kRegTypeYmm, 4, 32);
const YmmReg ymm5(kRegTypeYmm, 5, 32);
const YmmReg ymm6(kRegTypeYmm, 6, 32);
const YmmReg ymm7(kRegTypeYmm, 7, 32);
const YmmReg ymm8(kRegTypeYmm, 8, 32);
const YmmReg ymm9(kRegTypeYmm, 9, 32);
const YmmReg ymm10(kRegTypeYmm, 10, 32);
const YmmReg ymm11(kRegTypeYmm, 11, 32);
const YmmReg ymm12(kRegTypeYmm, 12, 32);
const YmmReg ymm13(kRegTypeYmm, 13, 32);
const YmmReg ymm14(kRegTypeYmm, 14, 32);
const YmmReg ymm15(kRegTypeYmm, 15, 32);
const SegReg cs(kRegTypeSeg, kSegCs, 2);
const SegReg ss(kRegTypeSeg, kSegSs, 2);
const SegReg ds(kRegTypeSeg, kSegDs, 2);
const SegReg es(kRegTypeSeg, kSegEs, 2);
const SegReg fs(kRegTypeSeg, kSegFs, 2);
const SegReg gs(kRegTypeSeg, kSegGs, 2);
// ============================================================================
// [asmjit::Mem - abs[]]
// ============================================================================
Mem ptr_abs(Ptr pAbs, int32_t disp, uint32_t size) {
Mem m(NoInit);
m._init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeAbsolute, 0, kInvalidValue);
m._vmem.index = kInvalidValue;
m._vmem.displacement = static_cast<int32_t>((intptr_t)(pAbs + disp));
return m;
}
Mem ptr_abs(Ptr pAbs, const X86Reg& index, uint32_t shift, int32_t disp, uint32_t size) {
Mem m(NoInit);
uint32_t flags = shift << kMemShiftIndex;
if (index.isGp()) flags |= Mem::_getGpdFlags(reinterpret_cast<const BaseVar&>(index));
if (index.isXmm()) flags |= kMemVSibXmm << kMemVSibIndex;
if (index.isYmm()) flags |= kMemVSibYmm << kMemVSibIndex;
m._init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeAbsolute, flags, kInvalidValue);
m._vmem.index = index.getRegIndex();
m._vmem.displacement = static_cast<int32_t>((intptr_t)(pAbs + disp));
return m;
}
Mem ptr_abs(Ptr pAbs, const X86Var& index, uint32_t shift, int32_t disp, uint32_t size) {
Mem m(NoInit);
uint32_t flags = shift << kMemShiftIndex;
if (index.isGp()) flags |= Mem::_getGpdFlags(reinterpret_cast<const BaseVar&>(index));
if (index.isXmm()) flags |= kMemVSibXmm << kMemVSibIndex;
if (index.isYmm()) flags |= kMemVSibYmm << kMemVSibIndex;
m._init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeAbsolute, flags, kInvalidValue);
m._vmem.index = index.getId();
m._vmem.displacement = static_cast<int32_t>((intptr_t)(pAbs + disp));
return m;
}
} // x86x64 namespace
} // asmjit namespace
// ============================================================================
// [asmjit::x86]
// ============================================================================
#if defined(ASMJIT_BUILD_X86)
namespace asmjit {
namespace x86 {
const uint8_t _varMapping[kVarTypeCount] = {
/* 00: kVarTypeInt8 */ kVarTypeInt8,
/* 01: kVarTypeUInt8 */ kVarTypeUInt8,
/* 02: kVarTypeInt16 */ kVarTypeInt16,
/* 03: kVarTypeUInt16 */ kVarTypeUInt16,
/* 04: kVarTypeInt32 */ kVarTypeInt32,
/* 05: kVarTypeUInt32 */ kVarTypeUInt32,
/* 06: kVarTypeInt64 */ kVarTypeInvalid, // Invalid in 32-bit mode.
/* 07: kVarTypeUInt64 */ kVarTypeInvalid, // Invalid in 32-bit mode.
/* 08: kVarTypeIntPtr */ kVarTypeInt32, // Remapped.
/* 09: kVarTypeUIntPtr */ kVarTypeUInt32, // Remapped.
/* 10: kVarTypeFp32 */ kVarTypeFp32,
/* 11: kVarTypeFp64 */ kVarTypeFp64,
/* 12: kVarTypeMm */ kVarTypeMm,
/* 13: kVarTypeXmm */ kVarTypeXmm,
/* 14: kVarTypeXmmSs */ kVarTypeXmmSs,
/* 15: kVarTypeXmmPs */ kVarTypeXmmPs,
/* 16: kVarTypeXmmSd */ kVarTypeXmmSd,
/* 17: kVarTypeXmmPd */ kVarTypeXmmPd,
/* 18: kVarTypeYmm */ kVarTypeYmm,
/* 19: kVarTypeYmmPs */ kVarTypeYmmPs,
/* 20: kVarTypeYmmPd */ kVarTypeYmmPd
};
const GpReg zax(kRegTypeGpd, kRegIndexAx, 4);
const GpReg zcx(kRegTypeGpd, kRegIndexCx, 4);
const GpReg zdx(kRegTypeGpd, kRegIndexDx, 4);
const GpReg zbx(kRegTypeGpd, kRegIndexBx, 4);
const GpReg zsp(kRegTypeGpd, kRegIndexSp, 4);
const GpReg zbp(kRegTypeGpd, kRegIndexBp, 4);
const GpReg zsi(kRegTypeGpd, kRegIndexSi, 4);
const GpReg zdi(kRegTypeGpd, kRegIndexDi, 4);
} // x86 namespace
} // asmjit namespace
#endif // ASMJIT_BUILD_X86
// ============================================================================
// [asmjit::x64]
// ============================================================================
#if defined(ASMJIT_BUILD_X64)
namespace asmjit {
namespace x64 {
const uint8_t _varMapping[kVarTypeCount] = {
/* 00: kVarTypeInt8 */ kVarTypeInt8,
/* 01: kVarTypeUInt8 */ kVarTypeUInt8,
/* 02: kVarTypeInt16 */ kVarTypeInt16,
/* 03: kVarTypeUInt16 */ kVarTypeUInt16,
/* 04: kVarTypeInt32 */ kVarTypeInt32,
/* 05: kVarTypeUInt32 */ kVarTypeUInt32,
/* 06: kVarTypeInt64 */ kVarTypeInt64,
/* 07: kVarTypeUInt64 */ kVarTypeUInt64,
/* 08: kVarTypeIntPtr */ kVarTypeInt64, // Remapped.
/* 09: kVarTypeUIntPtr */ kVarTypeUInt64, // Remapped.
/* 10: kVarTypeFp32 */ kVarTypeFp32,
/* 11: kVarTypeFp64 */ kVarTypeFp64,
/* 12: kVarTypeMm */ kVarTypeMm,
/* 13: kVarTypeXmm */ kVarTypeXmm,
/* 14: kVarTypeXmmSs */ kVarTypeXmmSs,
/* 15: kVarTypeXmmPs */ kVarTypeXmmPs,
/* 16: kVarTypeXmmSd */ kVarTypeXmmSd,
/* 17: kVarTypeXmmPd */ kVarTypeXmmPd,
/* 18: kVarTypeYmm */ kVarTypeYmm,
/* 19: kVarTypeYmmPs */ kVarTypeYmmPs,
/* 20: kVarTypeYmmPd */ kVarTypeYmmPd
};
const GpReg zax(kRegTypeGpq, kRegIndexAx, 8);
const GpReg zcx(kRegTypeGpq, kRegIndexCx, 8);
const GpReg zdx(kRegTypeGpq, kRegIndexDx, 8);
const GpReg zbx(kRegTypeGpq, kRegIndexBx, 8);
const GpReg zsp(kRegTypeGpq, kRegIndexSp, 8);
const GpReg zbp(kRegTypeGpq, kRegIndexBp, 8);
const GpReg zsi(kRegTypeGpq, kRegIndexSi, 8);
const GpReg zdi(kRegTypeGpq, kRegIndexDi, 8);
} // x64 namespace
} // asmjit namespace
#endif // ASMJIT_BUILD_X64
#include "../apiend.h"
// [Guard]
#endif // ASMJIT_BUILD_X86 || ASMJIT_BUILD_X64

1988
src/asmjit/x86/x86operand.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,90 @@
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Export]
#define ASMJIT_EXPORTS
// [Guard]
#include "../build.h"
#if defined(ASMJIT_BUILD_X86) || defined(ASMJIT_BUILD_X64)
// [Dependencies - AsmJit]
#include "../x86/x86util.h"
// [Api-Begin]
#include "../apibegin.h"
namespace asmjit {
namespace x86x64 {
// ============================================================================
// [asmjit::x86x64::Cond]
// ============================================================================
#define CC_TO_INST(_Inst_) { \
_Inst_##o, \
_Inst_##no, \
_Inst_##b, \
_Inst_##ae, \
_Inst_##e, \
_Inst_##ne, \
_Inst_##be, \
_Inst_##a, \
_Inst_##s, \
_Inst_##ns, \
_Inst_##pe, \
_Inst_##po, \
_Inst_##l, \
_Inst_##ge, \
_Inst_##le, \
_Inst_##g, \
\
kInstNone, \
kInstNone, \
kInstNone, \
kInstNone \
}
const uint32_t _reverseCond[20] = {
/* kCondO -> */ kCondO,
/* kCondNO -> */ kCondNO,
/* kCondB -> */ kCondA,
/* kCondAE -> */ kCondBE,
/* kCondE -> */ kCondE,
/* kCondNE -> */ kCondNE,
/* kCondBE -> */ kCondAE,
/* kCondA -> */ kCondB,
/* kCondS -> */ kCondS,
/* kCondNS -> */ kCondNS,
/* kCondPE -> */ kCondPE,
/* kCondPO -> */ kCondPO,
/* kCondL -> */ kCondG,
/* kCondGE -> */ kCondLE,
/* kCondLE -> */ kCondGE,
/* kCondG -> */ kCondL,
/* kCondFpuUnordered -> */ kCondFpuUnordered,
/* kCondFpuNotUnordered -> */ kCondFpuNotUnordered,
0x12,
0x13
};
const uint32_t _condToCmovcc[20] = CC_TO_INST(kInstCmov);
const uint32_t _condToJcc [20] = CC_TO_INST(kInstJ );
const uint32_t _condToSetcc [20] = CC_TO_INST(kInstSet );
#undef CC_TO_INST
} // x86x64 namespace
} // asmjit namespace
#include "../apiend.h"
// [Guard]
#endif // ASMJIT_BUILD_X86 || ASMJIT_BUILD_X64

369
src/asmjit/x86/x86util.h Normal file
View File

@@ -0,0 +1,369 @@
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Guard]
#ifndef _ASMJIT_X86_X86UTIL_H
#define _ASMJIT_X86_X86UTIL_H
// [Dependencies - AsmJit]
#include "../base/func.h"
#include "../x86/x86inst.h"
#include "../x86/x86operand.h"
// [Api-Begin]
#include "../apibegin.h"
namespace asmjit {
namespace x86x64 {
//! \addtogroup asmjit_x86x64_util
//! \{
// ============================================================================
// [asmjit::x86x64::Internal]
// ============================================================================
//! \internal
//!
//! X86/X64 condition codes to reversed condition codes map.
ASMJIT_VAR const uint32_t _reverseCond[20];
//! \internal
//!
//! X86X64 condition codes to "cmovcc" group map.
ASMJIT_VAR const uint32_t _condToCmovcc[20];
//! \internal
//!
//! X86X64 condition codes to "jcc" group map.
ASMJIT_VAR const uint32_t _condToJcc[20];
//! \internal
//!
//! X86X64 condition codes to "setcc" group map.
ASMJIT_VAR const uint32_t _condToSetcc[20];
// ============================================================================
// [asmjit::x86x64::RegCount]
// ============================================================================
//! \internal
//!
//! X86/X64 registers count (Gp, Fp, Mm, Xmm).
struct RegCount {
// --------------------------------------------------------------------------
// [Zero]
// --------------------------------------------------------------------------
ASMJIT_INLINE void reset() {
_packed = 0;
}
// --------------------------------------------------------------------------
// [Get]
// --------------------------------------------------------------------------
ASMJIT_INLINE uint32_t get(uint32_t c) const {
ASMJIT_ASSERT(c < kRegClassCount);
return _regs[c];
}
// --------------------------------------------------------------------------
// [Set]
// --------------------------------------------------------------------------
ASMJIT_INLINE void set(uint32_t c, uint32_t n) {
ASMJIT_ASSERT(c < kRegClassCount);
ASMJIT_ASSERT(n < 0x100);
_regs[c] = static_cast<uint8_t>(n);
}
// --------------------------------------------------------------------------
// [Add]
// --------------------------------------------------------------------------
ASMJIT_INLINE void add(uint32_t c, uint32_t n = 1) {
ASMJIT_ASSERT(c < kRegClassCount);
ASMJIT_ASSERT(n < 0x100);
_regs[c] += static_cast<uint8_t>(n);
}
// --------------------------------------------------------------------------
// [Misc]
// --------------------------------------------------------------------------
ASMJIT_INLINE void makeIndex(const RegCount& count) {
uint8_t a = count._regs[0];
uint8_t b = count._regs[1];
uint8_t c = count._regs[2];
_regs[0] = 0;
_regs[1] = a;
_regs[2] = a + b;
_regs[3] = a + b + c;
}
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
union {
struct {
uint8_t _gp;
uint8_t _fp;
uint8_t _mm;
uint8_t _xy;
};
uint8_t _regs[4];
uint32_t _packed;
};
};
// ============================================================================
// [asmjit::x86x64::RegMask]
// ============================================================================
//! \internal
//!
//! X86/X64 registers mask (Gp, Fp, Mm, Xmm/Ymm/Zmm).
struct RegMask {
// --------------------------------------------------------------------------
// [Reset]
// --------------------------------------------------------------------------
ASMJIT_INLINE void reset() {
_packed.reset();
}
// --------------------------------------------------------------------------
// [IsEmpty / Has]
// --------------------------------------------------------------------------
ASMJIT_INLINE bool isEmpty() const {
return _packed.isZero();
}
ASMJIT_INLINE bool has(uint32_t c, uint32_t mask = 0xFFFFFFFF) const {
switch (c) {
case kRegClassGp : return (static_cast<uint32_t>(_gp ) & mask) != 0;
case kRegClassFp : return (static_cast<uint32_t>(_fp ) & mask) != 0;
case kRegClassMm : return (static_cast<uint32_t>(_mm ) & mask) != 0;
case kRegClassXyz: return (static_cast<uint32_t>(_xyz) & mask) != 0;
}
ASMJIT_ASSERT(!"Reached");
return false;
}
// --------------------------------------------------------------------------
// [Zero]
// --------------------------------------------------------------------------
ASMJIT_INLINE void zero(uint32_t c) {
switch (c) {
case kRegClassGp : _gp = 0; break;
case kRegClassFp : _fp = 0; break;
case kRegClassMm : _mm = 0; break;
case kRegClassXyz: _xyz = 0; break;
}
}
// --------------------------------------------------------------------------
// [Get]
// --------------------------------------------------------------------------
ASMJIT_INLINE uint32_t get(uint32_t c) const {
switch (c) {
case kRegClassGp : return _gp;
case kRegClassFp : return _fp;
case kRegClassMm : return _mm;
case kRegClassXyz: return _xyz;
}
ASMJIT_ASSERT(!"Reached");
return 0;
}
// --------------------------------------------------------------------------
// [Set]
// --------------------------------------------------------------------------
ASMJIT_INLINE void set(uint32_t c, uint32_t mask) {
switch (c) {
case kRegClassGp : _gp = static_cast<uint16_t>(mask); break;
case kRegClassFp : _fp = static_cast<uint8_t >(mask); break;
case kRegClassMm : _mm = static_cast<uint8_t >(mask); break;
case kRegClassXyz: _xyz = static_cast<uint32_t>(mask); break;
}
}
ASMJIT_INLINE void set(const RegMask& other) {
_packed.setUInt64(other._packed);
}
// --------------------------------------------------------------------------
// [Add]
// --------------------------------------------------------------------------
ASMJIT_INLINE void add(uint32_t c, uint32_t mask) {
switch (c) {
case kRegClassGp : _gp |= static_cast<uint16_t>(mask); break;
case kRegClassFp : _fp |= static_cast<uint8_t >(mask); break;
case kRegClassMm : _mm |= static_cast<uint8_t >(mask); break;
case kRegClassXyz: _xyz |= static_cast<uint32_t>(mask); break;
}
}
ASMJIT_INLINE void add(const RegMask& other) {
_packed.or_(other._packed);
}
// --------------------------------------------------------------------------
// [Del]
// --------------------------------------------------------------------------
ASMJIT_INLINE void del(uint32_t c, uint32_t mask) {
switch (c) {
case kRegClassGp : _gp &= ~static_cast<uint16_t>(mask); break;
case kRegClassFp : _fp &= ~static_cast<uint8_t >(mask); break;
case kRegClassMm : _mm &= ~static_cast<uint8_t >(mask); break;
case kRegClassXyz: _xyz &= ~static_cast<uint32_t>(mask); break;
}
}
ASMJIT_INLINE void del(const RegMask& other) {
_packed.del(other._packed);
}
// --------------------------------------------------------------------------
// [And]
// --------------------------------------------------------------------------
ASMJIT_INLINE void and_(uint32_t c, uint32_t mask) {
switch (c) {
case kRegClassGp : _gp &= static_cast<uint16_t>(mask); break;
case kRegClassFp : _fp &= static_cast<uint8_t >(mask); break;
case kRegClassMm : _mm &= static_cast<uint8_t >(mask); break;
case kRegClassXyz: _xyz &= static_cast<uint32_t>(mask); break;
}
}
ASMJIT_INLINE void and_(const RegMask& other) {
_packed.and_(other._packed);
}
// --------------------------------------------------------------------------
// [Xor]
// --------------------------------------------------------------------------
ASMJIT_INLINE void xor_(uint32_t c, uint32_t mask) {
switch (c) {
case kRegClassGp : _gp ^= static_cast<uint16_t>(mask); break;
case kRegClassFp : _fp ^= static_cast<uint8_t >(mask); break;
case kRegClassMm : _mm ^= static_cast<uint8_t >(mask); break;
case kRegClassXyz: _xyz ^= static_cast<uint32_t>(mask); break;
}
}
ASMJIT_INLINE void xor_(const RegMask& other) {
_packed.xor_(other._packed);
}
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
union {
//! Gp mask (16-bit).
uint16_t _gp;
//! Fp mask (8-bit).
uint8_t _fp;
//! Mm mask (8-bit).
uint8_t _mm;
//! Xmm/Ymm/Zmm mask (32-bit).
uint32_t _xyz;
//! All masks as 64-bit integer.
UInt64 _packed;
};
};
// ============================================================================
// [asmjit::x86x64::X86Util]
// ============================================================================
//! X86/X64 utilities.
struct X86Util {
//! Corresponds to transposing the operands of a comparison.
static ASMJIT_INLINE uint32_t reverseCond(uint32_t cond) {
ASMJIT_ASSERT(cond < ASMJIT_ARRAY_SIZE(_reverseCond));
return _reverseCond[cond];
}
//! Get the equivalent of negated condition code.
static ASMJIT_INLINE uint32_t negateCond(uint32_t cond) {
ASMJIT_ASSERT(cond < ASMJIT_ARRAY_SIZE(_reverseCond));
return static_cast<kCond>(cond ^ static_cast<uint32_t>(cond < kCondNone));
}
//! Translate condition code `cc` to `cmovcc` instruction code.
//! \sa \ref kInstCode, \ref _kInstCmovcc.
static ASMJIT_INLINE uint32_t condToCmovcc(uint32_t cond) {
ASMJIT_ASSERT(static_cast<uint32_t>(cond) < ASMJIT_ARRAY_SIZE(_condToCmovcc));
return _condToCmovcc[cond];
}
//! Translate condition code `cc` to `jcc` instruction code.
//! \sa \ref kInstCode, \ref _kInstJcc.
static ASMJIT_INLINE uint32_t condToJcc(uint32_t cond) {
ASMJIT_ASSERT(static_cast<uint32_t>(cond) < ASMJIT_ARRAY_SIZE(_condToJcc));
return _condToJcc[cond];
}
//! Translate condition code `cc` to `setcc` instruction code.
//! \sa \ref kInstCode, \ref _kInstSetcc.
static ASMJIT_INLINE uint32_t condToSetcc(uint32_t cond) {
ASMJIT_ASSERT(static_cast<uint32_t>(cond) < ASMJIT_ARRAY_SIZE(_condToSetcc));
return _condToSetcc[cond];
}
//! Get whether the `op` operand is Gpb-Lo or Gpb-Hi register.
static ASMJIT_INLINE bool isGpbRegOp(const Operand& op) {
const uint32_t mask = IntUtil::pack32_2x8_1x16(0xFF, 0xFF, ~(kRegTypePatchedGpbHi << 8) & 0xFF00);
return (op._packed[0].u32[0] & mask) == IntUtil::pack32_2x8_1x16(kOperandTypeReg, 1, 0x0000);
}
//! Pack a shuffle constant to be used with multimedia instrutions.
//!
//! \param z First component position, number at interval [0, 3] inclusive.
//! \param x Second component position, number at interval [0, 3] inclusive.
//! \param y Third component position, number at interval [0, 3] inclusive.
//! \param w Fourth component position, number at interval [0, 3] inclusive.
//!
//! Shuffle constants can be used to make immediate value for these intrinsics:
//! - `X86X64Assembler::pshufw()` and `X86X64Compiler::pshufw()`
//! - `X86X64Assembler::pshufd()` and `X86X64Compiler::pshufd()`
//! - `X86X64Assembler::pshufhw()` and `X86X64Compiler::pshufhw()`
//! - `X86X64Assembler::pshuflw()` and `X86X64Compiler::pshuflw()`
//! - `X86X64Assembler::shufps()` and `X86X64Compiler::shufps()`
static ASMJIT_INLINE uint32_t mmShuffle(uint32_t z, uint32_t y, uint32_t x, uint32_t w) {
return (z << 6) | (y << 4) | (x << 2) | w;
}
};
//! \}
} // x86x64 namespace
} // asmjit namespace
// [Api-End]
#include "../apiend.h"
// [Guard]
#endif // _ASMJIT_X86_X86UTIL_H

View File

@@ -1,408 +0,0 @@
# Doxyfile 1.8.7
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "AsmJit"
PROJECT_NUMBER = "1.1"
PROJECT_BRIEF = "Complete Remote and JIT Assembler for x86/x64"
OUTPUT_DIRECTORY = .
CREATE_SUBDIRS = NO
ALLOW_UNICODE_NAMES = NO
OUTPUT_LANGUAGE = English
# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
# descriptions after the members that are listed in the file and class
# documentation (similar to Javadoc). Set to NO to disable this.
# The default value is: YES.
BRIEF_MEMBER_DESC = YES
# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
# description of a member or function before the detailed description
#
# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
# The default value is: YES.
REPEAT_BRIEF = YES
# This tag implements a quasi-intelligent brief description abbreviator that is
# used to form the text in various listings. Each string in this list, if found
# as the leading text of the brief description, will be stripped from the text
# and the result, after processing the whole list, is used as the annotated
# text. Otherwise, the brief description is used as-is. If left blank, the
# following values are used ($name is automatically replaced with the name of
# the entity):The $name class, The $name widget, The $name file, is, provides,
# specifies, contains, represents, a, an and the.
ABBREVIATE_BRIEF =
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
# doxygen will generate a detailed section even if there is only a brief
# description.
# The default value is: NO.
ALWAYS_DETAILED_SEC = NO
# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
# inherited members of a class in the documentation of that class as if those
# members were ordinary class members. Constructors, destructors and assignment
# operators of the base classes will not be shown.
# The default value is: NO.
INLINE_INHERITED_MEMB = NO
# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
# before files name in the file list and in the header files. If set to NO the
# shortest path that makes the file name unique will be used
# The default value is: YES.
FULL_PATH_NAMES = YES
# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
# Stripping is only done if one of the specified strings matches the left-hand
# part of the path. The tag can be used to show relative paths in the file list.
# If left blank the directory from which doxygen is run is used as the path to
# strip.
#
# Note that you can specify absolute paths here, but also relative paths, which
# will be relative from the directory where doxygen is started.
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
STRIP_FROM_PATH =
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
# path mentioned in the documentation of a class, which tells the reader which
# header file to include in order to use a class. If left blank only the name of
# the header file containing the class definition is used. Otherwise one should
# specify the list of include paths that are normally passed to the compiler
# using the -I flag.
STRIP_FROM_INC_PATH =
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
# less readable) file names. This can be useful is your file systems doesn't
# support long names like on DOS, Mac, or CD-ROM.
# The default value is: NO.
SHORT_NAMES = NO
# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
# first line (until the first dot) of a Javadoc-style comment as the brief
# description. If set to NO, the Javadoc-style will behave just like regular Qt-
# style comments (thus requiring an explicit @brief command for a brief
# description.)
# The default value is: NO.
JAVADOC_AUTOBRIEF = NO
# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
# line (until the first dot) of a Qt-style comment as the brief description. If
# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
# requiring an explicit \brief command for a brief description.)
# The default value is: NO.
QT_AUTOBRIEF = NO
# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
# a brief description. This used to be the default behavior. The new default is
# to treat a multi-line C++ comment block as a detailed description. Set this
# tag to YES if you prefer the old behavior instead.
#
# Note that setting this tag to YES also means that rational rose comments are
# not recognized any more.
# The default value is: NO.
MULTILINE_CPP_IS_BRIEF = NO
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
# documentation from any documented member that it re-implements.
# The default value is: YES.
INHERIT_DOCS = YES
# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
# new page for each member. If set to NO, the documentation of a member will be
# part of the file/class/namespace that contains it.
# The default value is: NO.
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 2
MARKDOWN_SUPPORT = YES
AUTOLINK_SUPPORT = NO
IDL_PROPERTY_SUPPORT = NO
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
# tag is set to YES, then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
# The default value is: NO.
DISTRIBUTE_GROUP_DOC = NO
# Set the SUBGROUPING tag to YES to allow class member groups of the same type
# (for instance a group of public functions) to be put as a subgroup of that
# type (e.g. under the Public Functions section). Set it to NO to prevent
# subgrouping. Alternatively, this can be done per class using the
# \nosubgrouping command.
# The default value is: YES.
SUBGROUPING = YES
# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
# are shown inside the group in which they are included (e.g. using \ingroup)
# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
# and RTF).
#
# Note that this feature does not work in combination with
# SEPARATE_MEMBER_PAGES.
# The default value is: NO.
INLINE_GROUPED_CLASSES = NO
# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
# with only public data fields or simple typedef fields will be shown inline in
# the documentation of the scope in which they are defined (i.e. file,
# namespace, or group documentation), provided this scope is documented. If set
# to NO, structs, classes, and unions are shown on a separate page (for HTML and
# Man pages) or section (for LaTeX and RTF).
# The default value is: NO.
INLINE_SIMPLE_STRUCTS = NO
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = NO
EXTRACT_PRIVATE = NO
EXTRACT_PACKAGE = NO
EXTRACT_STATIC = NO
EXTRACT_LOCAL_CLASSES = NO
HIDE_UNDOC_CLASSES = YES
HIDE_FRIEND_COMPOUNDS = YES
HIDE_IN_BODY_DOCS = YES
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = NO
# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
# their full class and namespace scopes in the documentation. If set to YES the
# scope will be hidden.
# The default value is: NO.
HIDE_SCOPE_NAMES = NO
SHOW_INCLUDE_FILES = NO
SHOW_GROUPED_MEMB_INC = NO
INLINE_INFO = YES
SORT_MEMBER_DOCS = NO
SORT_BRIEF_DOCS = NO
SORT_GROUP_NAMES = NO
SORT_BY_SCOPE_NAME = YES
STRICT_PROTO_MATCHING = NO
GENERATE_TODOLIST = NO
GENERATE_TESTLIST = NO
GENERATE_BUGLIST = NO
GENERATE_DEPRECATEDLIST= NO
MAX_INITIALIZER_LINES = 0
SHOW_USED_FILES = NO
SHOW_FILES = NO
SHOW_NAMESPACES = NO
#---------------------------------------------------------------------------
# Configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = YES
WARNINGS = YES
WARN_IF_UNDOCUMENTED = NO
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
#---------------------------------------------------------------------------
# Configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = ../src/asmjit
INPUT_ENCODING = UTF-8
RECURSIVE = YES
EXCLUDE =
USE_MDFILE_AS_MAINPAGE = ../README.md
#---------------------------------------------------------------------------
# Configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = NO
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
SOURCE_TOOLTIPS = YES
VERBATIM_HEADERS = NO
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = NO
#---------------------------------------------------------------------------
# Configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
GENERATE_LATEX = NO
GENERATE_RTF = NO
GENERATE_MAN = NO
HTML_OUTPUT = doc
HTML_FILE_EXTENSION = .html
LAYOUT_FILE = doc-layout.xml
HTML_HEADER = doc-header.html
HTML_FOOTER = doc-footer.html
HTML_STYLESHEET = doc-style.css
HTML_EXTRA_STYLESHEET =
HTML_EXTRA_FILES =
HTML_COLORSTYLE_HUE = 220
HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_GAMMA = 80
HTML_TIMESTAMP = NO
HTML_DYNAMIC_SECTIONS = NO
HTML_INDEX_NUM_ENTRIES = 0
SEARCHENGINE = NO
#---------------------------------------------------------------------------
# Configuration options related to the CHM output
#---------------------------------------------------------------------------
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
# Windows.
#
# The HTML Help Workshop contains a compiler that can convert all HTML output
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
# files are now used as the Windows 98 help format, and will replace the old
# Windows help format (.hlp) on all Windows platforms in the future. Compressed
# HTML files also contain an index, a table of contents, and you can search for
# words in the documentation. The HTML workshop also contains a viewer for
# compressed HTML files.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_HTMLHELP = NO
# The CHM_FILE tag can be used to specify the file name of the resulting .chm
# file. You can add a path in front of the file if the result should not be
# written to the html output directory.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_FILE =
# The HHC_LOCATION tag can be used to specify the location (absolute path
# including file name) of the HTML help compiler ( hhc.exe). If non-empty
# doxygen will try to run the HTML help compiler on the generated index.hhp.
# The file has to be specified with full path.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
HHC_LOCATION =
# The BINARY_TOC flag controls whether a binary table of contents is generated (
# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
# enables the Previous and Next buttons.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
BINARY_TOC = NO
# The TOC_EXPAND flag can be set to YES to add extra items for group members to
# the table of contents of the HTML help documentation and to the tree view.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
TOC_EXPAND = NO
# If you want full control over the layout of the generated HTML pages it might
# be necessary to disable the index and replace it with your own. The
# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
# of each HTML page. A value of NO enables the index and the value YES disables
# it. Since the tabs in the index contain the same information as the navigation
# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
DISABLE_INDEX = NO
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
# structure should be generated to display hierarchical information. If the tag
# value is set to YES, a side panel will be generated containing a tree-like
# index structure (just like the one that is generated for HTML Help). For this
# to work a browser that supports JavaScript, DHTML, CSS and frames is required
# (i.e. any modern browser). Windows users are probably better off using the
# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
# further fine-tune the look of the index. As an example, the default style
# sheet generated by doxygen has an example that shows how to put an image at
# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
# the same information as the tab index, you could consider setting
# DISABLE_INDEX to YES when enabling this option.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_TREEVIEW = NO
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
# doxygen will group on one line in the generated HTML documentation.
#
# Note that a value of 0 will completely suppress the enum values from appearing
# in the overview section.
# Minimum value: 0, maximum value: 20, default value: 4.
# This tag requires that the tag GENERATE_HTML is set to YES.
ENUM_VALUES_PER_LINE = 0
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
# to set the initial width (in pixels) of the frame in which the tree is shown.
# Minimum value: 0, maximum value: 1500, default value: 250.
# This tag requires that the tag GENERATE_HTML is set to YES.
TREEVIEW_WIDTH = 250
# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
# external symbols imported via tag files in a separate window.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
EXT_LINKS_IN_WINDOW = NO
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = NO
PREDEFINED = ASMJIT_DOCGEN=1
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = NO
CLASS_GRAPH = NO

View File

@@ -1,5 +1,5 @@
<!DOCTYPE html>
<html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>

View File

@@ -14,7 +14,6 @@
<class>
<briefdescription title=""/>
<inheritancegraph visible="$CLASS_GRAPH"/>
<detaileddescription title=""/>
<memberdecl>
<nestedclasses visible="yes" title=""/>
<publictypes title=""/>
@@ -49,6 +48,7 @@
<related title="" subtitle=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<inlineclasses title=""/>
<typedefs title=""/>
@@ -67,8 +67,8 @@
<!-- Layout definition for a group page -->
<group>
<briefdescription title=""/>
<groupgraph visible="$GROUP_GRAPHS"/>
<detaileddescription title=""/>
<memberdecl>
<nestedgroups visible="yes" title=""/>
<dirs visible="yes" title=""/>
@@ -90,6 +90,7 @@
<friends title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<pagedocs/>
<inlineclasses title=""/>
@@ -107,6 +108,5 @@
<properties title=""/>
<friends title=""/>
</memberdef>
<authorsection visible="yes"/>
</group>
</doxygenlayout>

View File

@@ -531,18 +531,9 @@ table.memberdecls {
background-image:url('nav_g.png');
background-repeat:repeat-x;
background-color: #FFFFFF;
/* opera specific markup */
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
/* firefox specific markup */
-moz-border-radius-bottomleft: 4px;
-moz-border-radius-bottomright: 4px;
-moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;
/* webkit specific markup */
-webkit-border-bottom-left-radius: 4px;
-webkit-border-bottom-right-radius: 4px;
-webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
/* box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); */
}
dl.reflist dt {
@@ -827,11 +818,11 @@ table.fieldtable {
.fieldtable td.fieldname {
padding-top: 3px;
font-weight: bold;
}
.fieldtable td.fielddoc {
border-bottom: 1px solid #A8B8D9;
/*width: 100%;*/
}
.fieldtable td.fielddoc p:first-child {
@@ -966,8 +957,8 @@ dl {
/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */
dl.section {
margin-left: 0px;
padding-left: 0px;
margin-left: 0;
padding-left: 0;
}
dl.note {
@@ -977,6 +968,10 @@ dl.note {
border-color: #D0C000;
}
dl.note dd {
margin-left: 0;
}
dl.warning, dl.attention {
margin-left:-7px;
padding-left: 3px;

View File

@@ -225,7 +225,7 @@ var main = function(files) {
main([
{
name: "../src/asmjit/x86/x86defs.cpp",
name: "../src/asmjit/x86/x86inst.cpp",
arch: "x86",
suffixes: [
"a", "ae",