mirror of
https://github.com/asmjit/asmjit.git
synced 2025-12-17 12:34:35 +03:00
- 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:
@@ -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
236
Doxyfile
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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)));
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
};
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#define ASMJIT_EXPORTS
|
||||
|
||||
// [Dependencies - AsmJit]
|
||||
#include "../base/defs.h"
|
||||
#include "../base/operand.h"
|
||||
|
||||
// [Api-Begin]
|
||||
#include "../apibegin.h"
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#define ASMJIT_EXPORTS
|
||||
|
||||
// [Dependencies - AsmJit]
|
||||
#include "../base/defs.h"
|
||||
#include "../base/intutil.h"
|
||||
#include "../base/string.h"
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#define ASMJIT_EXPORTS
|
||||
|
||||
// [Dependencies - AsmJit]
|
||||
#include "../base/defs.h"
|
||||
#include "../base/intutil.h"
|
||||
#include "../base/zone.h"
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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]
|
||||
// ============================================================================
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
111
src/asmjit/x86.h
111
src/asmjit/x86.h
@@ -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
|
||||
|
||||
@@ -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,113 +351,108 @@ 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 (IntUtil::hasBit(_features, kCodeGenOptimizedAlign)) {
|
||||
const CpuInfo* cpuInfo = static_cast<const CpuInfo*>(getRuntime()->getCpuInfo());
|
||||
if (mode == kAlignCode) {
|
||||
alignPattern = 0x90;
|
||||
|
||||
// NOPs optimized for Intel:
|
||||
// Intel 64 and IA-32 Architectures Software Developer's Manual
|
||||
// - Volume 2B
|
||||
// - Instruction Set Reference N-Z
|
||||
// - NOP
|
||||
if (IntUtil::hasBit(_features, kCodeGenOptimizedAlign)) {
|
||||
const CpuInfo* cpuInfo = static_cast<const CpuInfo*>(getRuntime()->getCpuInfo());
|
||||
|
||||
// NOPs optimized for AMD:
|
||||
// Software Optimization Guide for AMD Family 10h Processors (Quad-Core)
|
||||
// - 4.13 - Code Padding with Operand-Size Override and Multibyte NOP
|
||||
// NOPs optimized for Intel:
|
||||
// Intel 64 and IA-32 Architectures Software Developer's Manual
|
||||
// - Volume 2B
|
||||
// - Instruction Set Reference N-Z
|
||||
// - NOP
|
||||
|
||||
// Intel and AMD.
|
||||
static const uint8_t nop1[] = { 0x90 };
|
||||
static const uint8_t nop2[] = { 0x66, 0x90 };
|
||||
static const uint8_t nop3[] = { 0x0F, 0x1F, 0x00 };
|
||||
static const uint8_t nop4[] = { 0x0F, 0x1F, 0x40, 0x00 };
|
||||
static const uint8_t nop5[] = { 0x0F, 0x1F, 0x44, 0x00, 0x00 };
|
||||
static const uint8_t nop6[] = { 0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00 };
|
||||
static const uint8_t nop7[] = { 0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00 };
|
||||
static const uint8_t nop8[] = { 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
static const uint8_t nop9[] = { 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
// NOPs optimized for AMD:
|
||||
// Software Optimization Guide for AMD Family 10h Processors (Quad-Core)
|
||||
// - 4.13 - Code Padding with Operand-Size Override and Multibyte NOP
|
||||
|
||||
// AMD.
|
||||
static const uint8_t nop10[] = { 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
static const uint8_t nop11[] = { 0x66, 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
// Intel and AMD.
|
||||
static const uint8_t nop1[] = { 0x90 };
|
||||
static const uint8_t nop2[] = { 0x66, 0x90 };
|
||||
static const uint8_t nop3[] = { 0x0F, 0x1F, 0x00 };
|
||||
static const uint8_t nop4[] = { 0x0F, 0x1F, 0x40, 0x00 };
|
||||
static const uint8_t nop5[] = { 0x0F, 0x1F, 0x44, 0x00, 0x00 };
|
||||
static const uint8_t nop6[] = { 0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00 };
|
||||
static const uint8_t nop7[] = { 0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00 };
|
||||
static const uint8_t nop8[] = { 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
static const uint8_t nop9[] = { 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
const uint8_t* p;
|
||||
uint32_t n;
|
||||
// AMD.
|
||||
static const uint8_t nop10[] = { 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
static const uint8_t nop11[] = { 0x66, 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
if (cpuInfo->getVendorId() == kCpuVendorIntel && ((cpuInfo->getFamily() & 0x0F) == 0x06 || (cpuInfo->getFamily() & 0x0F) == 0x0F)) {
|
||||
do {
|
||||
switch (i) {
|
||||
case 1: p = nop1; n = 1; break;
|
||||
case 2: p = nop2; n = 2; break;
|
||||
case 3: p = nop3; n = 3; break;
|
||||
case 4: p = nop4; n = 4; break;
|
||||
case 5: p = nop5; n = 5; break;
|
||||
case 6: p = nop6; n = 6; break;
|
||||
case 7: p = nop7; n = 7; break;
|
||||
case 8: p = nop8; n = 8; break;
|
||||
default: p = nop9; n = 9; break;
|
||||
}
|
||||
const uint8_t* p;
|
||||
uint32_t n;
|
||||
|
||||
i -= n;
|
||||
if (cpuInfo->getVendorId() == kCpuVendorIntel && (
|
||||
(cpuInfo->getFamily() & 0x0F) == 0x06 ||
|
||||
(cpuInfo->getFamily() & 0x0F) == 0x0F)) {
|
||||
do {
|
||||
EMIT_BYTE(*p++);
|
||||
} while (--n);
|
||||
} while (i);
|
||||
}
|
||||
else if (cpuInfo->getVendorId() == kCpuVendorAmd && cpuInfo->getFamily() >= 0x0F) {
|
||||
do {
|
||||
switch (i) {
|
||||
case 1: p = nop1 ; n = 1; break;
|
||||
case 2: p = nop2 ; n = 2; break;
|
||||
case 3: p = nop3 ; n = 3; break;
|
||||
case 4: p = nop4 ; n = 4; break;
|
||||
case 5: p = nop5 ; n = 5; break;
|
||||
case 6: p = nop6 ; n = 6; break;
|
||||
case 7: p = nop7 ; n = 7; break;
|
||||
case 8: p = nop8 ; n = 8; break;
|
||||
case 9: p = nop9 ; n = 9; break;
|
||||
case 10: p = nop10; n = 10; break;
|
||||
default: p = nop11; n = 11; break;
|
||||
}
|
||||
switch (i) {
|
||||
case 1: p = nop1; n = 1; break;
|
||||
case 2: p = nop2; n = 2; break;
|
||||
case 3: p = nop3; n = 3; break;
|
||||
case 4: p = nop4; n = 4; break;
|
||||
case 5: p = nop5; n = 5; break;
|
||||
case 6: p = nop6; n = 6; break;
|
||||
case 7: p = nop7; n = 7; break;
|
||||
case 8: p = nop8; n = 8; break;
|
||||
default: p = nop9; n = 9; break;
|
||||
}
|
||||
|
||||
i -= n;
|
||||
i -= n;
|
||||
do {
|
||||
EMIT_BYTE(*p++);
|
||||
} while (--n);
|
||||
} while (i);
|
||||
}
|
||||
else if (cpuInfo->getVendorId() == kCpuVendorAmd && cpuInfo->getFamily() >= 0x0F) {
|
||||
do {
|
||||
EMIT_BYTE(*p++);
|
||||
} while (--n);
|
||||
} while (i);
|
||||
}
|
||||
switch (i) {
|
||||
case 1: p = nop1 ; n = 1; break;
|
||||
case 2: p = nop2 ; n = 2; break;
|
||||
case 3: p = nop3 ; n = 3; break;
|
||||
case 4: p = nop4 ; n = 4; break;
|
||||
case 5: p = nop5 ; n = 5; break;
|
||||
case 6: p = nop6 ; n = 6; break;
|
||||
case 7: p = nop7 ; n = 7; break;
|
||||
case 8: p = nop8 ; n = 8; break;
|
||||
case 9: p = nop9 ; n = 9; break;
|
||||
case 10: p = nop10; n = 10; break;
|
||||
default: p = nop11; n = 11; break;
|
||||
}
|
||||
|
||||
// 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--;
|
||||
}
|
||||
i -= n;
|
||||
do {
|
||||
EMIT_BYTE(*p++);
|
||||
} while (--n);
|
||||
} while (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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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, ®s.edx, 4);
|
||||
::memcpy(cpuInfo->_vendorString + 8, ®s.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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
1837
src/asmjit/x86/x86inst.h
Normal file
File diff suppressed because it is too large
Load Diff
338
src/asmjit/x86/x86operand.cpp
Normal file
338
src/asmjit/x86/x86operand.cpp
Normal 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
1988
src/asmjit/x86/x86operand.h
Normal file
File diff suppressed because it is too large
Load Diff
90
src/asmjit/x86/x86util.cpp
Normal file
90
src/asmjit/x86/x86util.cpp
Normal 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
369
src/asmjit/x86/x86util.h
Normal 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
|
||||
408
tools/Doxyfile
408
tools/Doxyfile
@@ -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
|
||||
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user