Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
tsoc
openmm
Commits
61d5cc0f
Commit
61d5cc0f
authored
Apr 16, 2015
by
Peter
Browse files
Merge branch 'master' into applecl
parents
e2999354
afae4bc8
Changes
232
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
5160 additions
and
0 deletions
+5160
-0
libraries/asmjit/base/constpool.h
libraries/asmjit/base/constpool.h
+303
-0
libraries/asmjit/base/containers.cpp
libraries/asmjit/base/containers.cpp
+116
-0
libraries/asmjit/base/containers.h
libraries/asmjit/base/containers.h
+350
-0
libraries/asmjit/base/context.cpp
libraries/asmjit/base/context.cpp
+561
-0
libraries/asmjit/base/context_p.h
libraries/asmjit/base/context_p.h
+307
-0
libraries/asmjit/base/cpuinfo.cpp
libraries/asmjit/base/cpuinfo.cpp
+79
-0
libraries/asmjit/base/cpuinfo.h
libraries/asmjit/base/cpuinfo.h
+147
-0
libraries/asmjit/base/cputicks.cpp
libraries/asmjit/base/cputicks.cpp
+131
-0
libraries/asmjit/base/cputicks.h
libraries/asmjit/base/cputicks.h
+40
-0
libraries/asmjit/base/error.cpp
libraries/asmjit/base/error.cpp
+83
-0
libraries/asmjit/base/error.h
libraries/asmjit/base/error.h
+218
-0
libraries/asmjit/base/globals.cpp
libraries/asmjit/base/globals.cpp
+30
-0
libraries/asmjit/base/globals.h
libraries/asmjit/base/globals.h
+177
-0
libraries/asmjit/base/intutil.cpp
libraries/asmjit/base/intutil.cpp
+210
-0
libraries/asmjit/base/intutil.h
libraries/asmjit/base/intutil.h
+739
-0
libraries/asmjit/base/lock.h
libraries/asmjit/base/lock.h
+131
-0
libraries/asmjit/base/logger.cpp
libraries/asmjit/base/logger.cpp
+161
-0
libraries/asmjit/base/logger.h
libraries/asmjit/base/logger.h
+249
-0
libraries/asmjit/base/operand.cpp
libraries/asmjit/base/operand.cpp
+38
-0
libraries/asmjit/base/operand.h
libraries/asmjit/base/operand.h
+1090
-0
No files found.
Too many changes to show.
To preserve performance only
232 of 232+
files are displayed.
Plain diff
Email patch
libraries/asmjit/base/constpool.h
0 → 100644
View file @
61d5cc0f
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Guard]
#ifndef _ASMJIT_BASE_CONSTPOOL_H
#define _ASMJIT_BASE_CONSTPOOL_H
// [Dependencies - AsmJit]
#include "../base/error.h"
#include "../base/zone.h"
// [Api-Begin]
#include "../apibegin.h"
namespace
asmjit
{
//! \addtogroup asmjit_base_util
//! \{
// ============================================================================
// [asmjit::ConstPoolNode]
// ============================================================================
//! \internal
//!
//! Zone-allocated constant-pool node.
struct
ConstPoolNode
{
// --------------------------------------------------------------------------
// [Accessors]
// --------------------------------------------------------------------------
ASMJIT_INLINE
void
*
getData
()
const
{
return
static_cast
<
void
*>
(
const_cast
<
ConstPoolNode
*>
(
this
)
+
1
);
}
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
//! Left/Right nodes.
ConstPoolNode
*
_link
[
2
];
//! Horizontal level for balance.
uint32_t
_level
:
31
;
//! Whether this constant is shared with another.
uint32_t
_shared
:
1
;
//! Data offset from the beginning of the pool.
uint32_t
_offset
;
};
// ============================================================================
// [asmjit::ConstPoolTree]
// ============================================================================
//! \internal
//!
//! Zone-allocated constant-pool tree.
struct
ConstPoolTree
{
enum
{
//! Maximum tree height == log2(1 << 64).
kHeightLimit
=
64
};
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
ASMJIT_INLINE
ConstPoolTree
(
size_t
dataSize
=
0
)
:
_root
(
NULL
),
_length
(
0
),
_dataSize
(
dataSize
)
{}
ASMJIT_INLINE
~
ConstPoolTree
()
{}
// --------------------------------------------------------------------------
// [Reset]
// --------------------------------------------------------------------------
ASMJIT_INLINE
void
reset
()
{
_root
=
NULL
;
_length
=
0
;
}
// --------------------------------------------------------------------------
// [Accessors]
// --------------------------------------------------------------------------
ASMJIT_INLINE
bool
isEmpty
()
const
{
return
_length
==
0
;
}
ASMJIT_INLINE
size_t
getLength
()
const
{
return
_length
;
}
ASMJIT_INLINE
void
setDataSize
(
size_t
dataSize
)
{
ASMJIT_ASSERT
(
isEmpty
());
_dataSize
=
dataSize
;
}
// --------------------------------------------------------------------------
// [Ops]
// --------------------------------------------------------------------------
ASMJIT_API
ConstPoolNode
*
get
(
const
void
*
data
);
ASMJIT_API
void
put
(
ConstPoolNode
*
node
);
// --------------------------------------------------------------------------
// [Iterate]
// --------------------------------------------------------------------------
template
<
typename
Visitor
>
ASMJIT_INLINE
void
iterate
(
Visitor
&
visitor
)
const
{
ConstPoolNode
*
node
=
const_cast
<
ConstPoolNode
*>
(
_root
);
ConstPoolNode
*
link
;
ConstPoolNode
*
stack
[
kHeightLimit
];
if
(
node
==
NULL
)
return
;
size_t
top
=
0
;
for
(;;)
{
link
=
node
->
_link
[
0
];
if
(
link
!=
NULL
)
{
ASMJIT_ASSERT
(
top
!=
kHeightLimit
);
stack
[
top
++
]
=
node
;
node
=
link
;
continue
;
}
_Visit:
visitor
.
visit
(
node
);
link
=
node
->
_link
[
1
];
if
(
link
!=
NULL
)
{
node
=
link
;
continue
;
}
if
(
top
==
0
)
break
;
node
=
stack
[
--
top
];
goto
_Visit
;
}
}
// --------------------------------------------------------------------------
// [Helpers]
// --------------------------------------------------------------------------
static
ASMJIT_INLINE
ConstPoolNode
*
_newNode
(
Zone
*
zone
,
const
void
*
data
,
size_t
size
,
size_t
offset
,
bool
shared
)
{
ConstPoolNode
*
node
=
zone
->
allocT
<
ConstPoolNode
>
(
sizeof
(
ConstPoolNode
)
+
size
);
if
(
node
==
NULL
)
return
NULL
;
node
->
_link
[
0
]
=
NULL
;
node
->
_link
[
1
]
=
NULL
;
node
->
_level
=
1
;
node
->
_shared
=
shared
;
node
->
_offset
=
static_cast
<
uint32_t
>
(
offset
);
::
memcpy
(
node
->
getData
(),
data
,
size
);
return
node
;
}
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
//! Root of the tree
ConstPoolNode
*
_root
;
//! Length of the tree (count of nodes).
size_t
_length
;
//! Size of the data.
size_t
_dataSize
;
};
// ============================================================================
// [asmjit::ConstPoolGap]
// ============================================================================
//! \internal
//!
//! Zone-allocated constant-pool gap.
struct
ConstPoolGap
{
//! Link to the next gap
ConstPoolGap
*
_next
;
//! Offset of the gap.
size_t
_offset
;
//! Remaining bytes of the gap (basically a gap size).
size_t
_length
;
};
// ============================================================================
// [asmjit::ConstPool]
// ============================================================================
//! Constant pool.
struct
ConstPool
{
ASMJIT_NO_COPY
(
ConstPool
)
enum
{
kIndex1
=
0
,
kIndex2
=
1
,
kIndex4
=
2
,
kIndex8
=
3
,
kIndex16
=
4
,
kIndex32
=
5
,
kIndexCount
=
6
};
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
ASMJIT_API
ConstPool
(
Zone
*
zone
);
ASMJIT_API
~
ConstPool
();
// --------------------------------------------------------------------------
// [Reset]
// --------------------------------------------------------------------------
ASMJIT_API
void
reset
();
// --------------------------------------------------------------------------
// [Ops]
// --------------------------------------------------------------------------
//! Get whether the constant-pool is empty.
ASMJIT_INLINE
bool
isEmpty
()
const
{
return
_size
==
0
;
}
//! Get the size of the constant-pool in bytes.
ASMJIT_INLINE
size_t
getSize
()
const
{
return
_size
;
}
//! Get minimum alignment.
ASMJIT_INLINE
size_t
getAlignment
()
const
{
return
_alignment
;
}
//! Add a constant to the constant pool.
//!
//! The constant must have known size, which is 1, 2, 4, 8, 16 or 32 bytes.
//! The constant is added to the pool only if it doesn't not exist, otherwise
//! cached value is returned.
//!
//! AsmJit is able to subdivide added constants, so for example if you add
//! 8-byte constant 0x1122334455667788 it will create the following slots:
//!
//! 8-byte: 0x1122334455667788
//! 4-byte: 0x11223344, 0x55667788
//!
//! The reason is that when combining MMX/SSE/AVX code some patterns are used
//! frequently. However, AsmJit is not able to reallocate a constant that has
//! been already added. For example if you try to add 4-byte constant and then
//! 8-byte constant having the same 4-byte pattern as the previous one, two
//! independent slots will be generated by the pool.
ASMJIT_API
Error
add
(
const
void
*
data
,
size_t
size
,
size_t
&
dstOffset
);
// --------------------------------------------------------------------------
// [Fill]
// --------------------------------------------------------------------------
//! Fill the destination with the constants from the pool.
ASMJIT_API
void
fill
(
void
*
dst
);
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
//! Zone allocator.
Zone
*
_zone
;
//! Tree per size.
ConstPoolTree
_tree
[
kIndexCount
];
//! Gaps per size.
ConstPoolGap
*
_gaps
[
kIndexCount
];
//! Gaps pool
ConstPoolGap
*
_gapPool
;
//! Size of the pool (in bytes).
size_t
_size
;
//! Alignemnt.
size_t
_alignment
;
};
//! \}
}
// asmjit namespace
// [Api-End]
#include "../apiend.h"
// [Guard]
#endif // _ASMJIT_BASE_CONSTPOOL_H
libraries/asmjit/base/containers.cpp
0 → 100644
View file @
61d5cc0f
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Export]
#define ASMJIT_EXPORTS
// [Dependencies - AsmJit]
#include "../base/containers.h"
#include "../base/intutil.h"
// [Api-Begin]
#include "../apibegin.h"
namespace
asmjit
{
// ============================================================================
// [asmjit::PodVectorBase - NullData]
// ============================================================================
const
PodVectorData
PodVectorBase
::
_nullData
=
{
0
,
0
};
// ============================================================================
// [asmjit::PodVectorBase - Reset]
// ============================================================================
//! Clear vector data and free internal buffer.
void
PodVectorBase
::
reset
(
bool
releaseMemory
)
{
PodVectorData
*
d
=
_d
;
if
(
d
==
&
_nullData
)
return
;
if
(
releaseMemory
)
{
ASMJIT_FREE
(
d
);
_d
=
const_cast
<
PodVectorData
*>
(
&
_nullData
);
return
;
}
d
->
length
=
0
;
}
// ============================================================================
// [asmjit::PodVectorBase - Helpers]
// ============================================================================
Error
PodVectorBase
::
_grow
(
size_t
n
,
size_t
sizeOfT
)
{
PodVectorData
*
d
=
_d
;
size_t
threshold
=
kMemAllocGrowMax
/
sizeOfT
;
size_t
capacity
=
d
->
capacity
;
size_t
after
=
d
->
length
;
if
(
IntUtil
::
maxUInt
<
size_t
>
()
-
n
<
after
)
return
kErrorNoHeapMemory
;
after
+=
n
;
if
(
capacity
>=
after
)
return
kErrorOk
;
// PodVector is used as a linear array for some data structures used by
// AsmJit code generation. The purpose of this agressive growing schema
// is to minimize memory reallocations, because AsmJit code generation
// classes live short life and will be freed or reused soon.
if
(
capacity
<
32
)
capacity
=
32
;
else
if
(
capacity
<
128
)
capacity
=
128
;
else
if
(
capacity
<
512
)
capacity
=
512
;
while
(
capacity
<
after
)
{
if
(
capacity
<
threshold
)
capacity
*=
2
;
else
capacity
+=
threshold
;
}
return
_reserve
(
capacity
,
sizeOfT
);
}
Error
PodVectorBase
::
_reserve
(
size_t
n
,
size_t
sizeOfT
)
{
PodVectorData
*
d
=
_d
;
if
(
d
->
capacity
>=
n
)
return
kErrorOk
;
size_t
nBytes
=
sizeof
(
PodVectorData
)
+
n
*
sizeOfT
;
if
(
nBytes
<
n
)
return
kErrorNoHeapMemory
;
if
(
d
==
&
_nullData
)
{
d
=
static_cast
<
PodVectorData
*>
(
ASMJIT_ALLOC
(
nBytes
));
if
(
d
==
NULL
)
return
kErrorNoHeapMemory
;
d
->
length
=
0
;
}
else
{
d
=
static_cast
<
PodVectorData
*>
(
ASMJIT_REALLOC
(
d
,
nBytes
));
if
(
d
==
NULL
)
return
kErrorNoHeapMemory
;
}
d
->
capacity
=
n
;
_d
=
d
;
return
kErrorOk
;
}
}
// asmjit namespace
// [Api-End]
#include "../apiend.h"
libraries/asmjit/base/containers.h
0 → 100644
View file @
61d5cc0f
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Guard]
#ifndef _ASMJIT_BASE_CONTAINERS_H
#define _ASMJIT_BASE_CONTAINERS_H
// [Dependencies - AsmJit]
#include "../base/error.h"
#include "../base/globals.h"
// [Api-Begin]
#include "../apibegin.h"
namespace
asmjit
{
//! \addtogroup asmjit_base_util
//! \{
// ============================================================================
// [asmjit::PodVectorData]
// ============================================================================
//! \internal
struct
PodVectorData
{
// --------------------------------------------------------------------------
// [Accessors]
// --------------------------------------------------------------------------
//! Get data.
ASMJIT_INLINE
void
*
getData
()
const
{
return
(
void
*
)(
this
+
1
);
}
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
//! Capacity of the vector.
size_t
capacity
;
//! Length of the vector.
size_t
length
;
};
// ============================================================================
// [asmjit::PodVectorBase]
// ============================================================================
//! \internal
struct
PodVectorBase
{
static
ASMJIT_API
const
PodVectorData
_nullData
;
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! Create a new instance of `PodVectorBase`.
ASMJIT_INLINE
PodVectorBase
()
:
_d
(
const_cast
<
PodVectorData
*>
(
&
_nullData
))
{}
//! Destroy the `PodVectorBase` and data.
ASMJIT_INLINE
~
PodVectorBase
()
{
reset
(
true
);
}
// --------------------------------------------------------------------------
// [Reset]
// --------------------------------------------------------------------------
//! Reset the vector data and set its `length` to zero.
//!
//! If `releaseMemory` is true the vector buffer will be released to the
//! system.
ASMJIT_API
void
reset
(
bool
releaseMemory
=
false
);
// --------------------------------------------------------------------------
// [Grow / Reserve]
// --------------------------------------------------------------------------
protected:
ASMJIT_API
Error
_grow
(
size_t
n
,
size_t
sizeOfT
);
ASMJIT_API
Error
_reserve
(
size_t
n
,
size_t
sizeOfT
);
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
public:
PodVectorData
*
_d
;
};
// ============================================================================
// [asmjit::PodVector<T>]
// ============================================================================
//! Template used to store and manage array of POD data.
//!
//! This template has these adventages over other vector<> templates:
//! - Non-copyable (designed to be non-copyable, we want it)
//! - No copy-on-write (some implementations of stl can use it)
//! - Optimized for working only with POD types
//! - Uses ASMJIT_... memory management macros
template
<
typename
T
>
struct
PodVector
:
PodVectorBase
{
ASMJIT_NO_COPY
(
PodVector
<
T
>
)
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! Create a new instance of `PodVector<T>`.
ASMJIT_INLINE
PodVector
()
{}
//! Destroy the `PodVector<>` and data.
ASMJIT_INLINE
~
PodVector
()
{}
// --------------------------------------------------------------------------
// [Data]
// --------------------------------------------------------------------------
//! Get whether the vector is empty.
ASMJIT_INLINE
bool
isEmpty
()
const
{
return
_d
->
length
==
0
;
}
//! Get length.
ASMJIT_INLINE
size_t
getLength
()
const
{
return
_d
->
length
;
}
//! Get capacity.
ASMJIT_INLINE
size_t
getCapacity
()
const
{
return
_d
->
capacity
;
}
//! Get data.
ASMJIT_INLINE
T
*
getData
()
{
return
static_cast
<
T
*>
(
_d
->
getData
());
}
//! \overload
ASMJIT_INLINE
const
T
*
getData
()
const
{
return
static_cast
<
const
T
*>
(
_d
->
getData
());
}
// --------------------------------------------------------------------------
// [Grow / Reserve]
// --------------------------------------------------------------------------
//! Called to grow the buffer to fit at least `n` elements more.
ASMJIT_INLINE
Error
_grow
(
size_t
n
)
{
return
PodVectorBase
::
_grow
(
n
,
sizeof
(
T
));
}
//! Realloc internal array to fit at least `n` items.
ASMJIT_INLINE
Error
_reserve
(
size_t
n
)
{
return
PodVectorBase
::
_reserve
(
n
,
sizeof
(
T
));
}
// --------------------------------------------------------------------------
// [Ops]
// --------------------------------------------------------------------------
//! Prepend `item` to vector.
Error
prepend
(
const
T
&
item
)
{
PodVectorData
*
d
=
_d
;
if
(
d
->
length
==
d
->
capacity
)
{
ASMJIT_PROPAGATE_ERROR
(
_grow
(
1
));
_d
=
d
;
}
::
memmove
(
static_cast
<
T
*>
(
d
->
getData
())
+
1
,
d
->
getData
(),
d
->
length
*
sizeof
(
T
));
::
memcpy
(
d
->
getData
(),
&
item
,
sizeof
(
T
));
d
->
length
++
;
return
kErrorOk
;
}
//! Insert an `item` at the `index`.
Error
insert
(
size_t
index
,
const
T
&
item
)
{
PodVectorData
*
d
=
_d
;
ASMJIT_ASSERT
(
index
<=
d
->
length
);
if
(
d
->
length
==
d
->
capacity
)
{
ASMJIT_PROPAGATE_ERROR
(
_grow
(
1
));
d
=
_d
;
}
T
*
dst
=
static_cast
<
T
*>
(
d
->
getData
())
+
index
;
::
memmove
(
dst
+
1
,
dst
,
d
->
length
-
index
);
::
memcpy
(
dst
,
&
item
,
sizeof
(
T
));
d
->
length
++
;
return
kErrorOk
;
}
//! Append `item` to vector.
Error
append
(
const
T
&
item
)
{
PodVectorData
*
d
=
_d
;
if
(
d
->
length
==
d
->
capacity
)
{
ASMJIT_PROPAGATE_ERROR
(
_grow
(
1
));
d
=
_d
;
}
::
memcpy
(
static_cast
<
T
*>
(
d
->
getData
())
+
d
->
length
,
&
item
,
sizeof
(
T
));
d
->
length
++
;
return
kErrorOk
;
}
//! Get index of `val` or `kInvalidIndex` if not found.
size_t
indexOf
(
const
T
&
val
)
const
{
PodVectorData
*
d
=
_d
;
const
T
*
data
=
static_cast
<
const
T
*>
(
d
->
getData
());
size_t
len
=
d
->
length
;
for
(
size_t
i
=
0
;
i
<
len
;
i
++
)
if
(
data
[
i
]
==
val
)
return
i
;
return
kInvalidIndex
;
}
//! Remove item at index `i`.
void
removeAt
(
size_t
i
)
{
PodVectorData
*
d
=
_d
;
ASMJIT_ASSERT
(
i
<
d
->
length
);
T
*
data
=
static_cast
<
T
*>
(
d
->
getData
())
+
i
;
d
->
length
--
;
::
memmove
(
data
,
data
+
1
,
d
->
length
-
i
);
}
//! Swap this pod-vector with `other`.
void
swap
(
PodVector
<
T
>&
other
)
{
T
*
otherData
=
other
.
_d
;
other
.
_d
=
_d
;
_d
=
otherData
;
}
//! Get item at index `i`.
ASMJIT_INLINE
T
&
operator
[](
size_t
i
)
{
ASMJIT_ASSERT
(
i
<
getLength
());
return
getData
()[
i
];
}
//! Get item at index `i`.
ASMJIT_INLINE
const
T
&
operator
[](
size_t
i
)
const
{
ASMJIT_ASSERT
(
i
<
getLength
());
return
getData
()[
i
];
}
};
// ============================================================================
// [asmjit::PodList<T>]
// ============================================================================
//! \internal
template
<
typename
T
>
struct
PodList
{
ASMJIT_NO_COPY
(
PodList
<
T
>
)
// --------------------------------------------------------------------------
// [Link]
// --------------------------------------------------------------------------
struct
Link
{
// --------------------------------------------------------------------------
// [Accessors]
// --------------------------------------------------------------------------
//! Get next node.
ASMJIT_INLINE
Link
*
getNext
()
const
{
return
_next
;
}
//! Get value.
ASMJIT_INLINE
T
getValue
()
const
{
return
_value
;
}
//! Set value to `value`.
ASMJIT_INLINE
void
setValue
(
const
T
&
value
)
{
_value
=
value
;
}
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
Link
*
_next
;
T
_value
;
};
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
ASMJIT_INLINE
PodList
()
:
_first
(
NULL
),
_last
(
NULL
)
{}
ASMJIT_INLINE
~
PodList
()
{}
// --------------------------------------------------------------------------
// [Data]
// --------------------------------------------------------------------------
ASMJIT_INLINE
bool
isEmpty
()
const
{
return
_first
!=
NULL
;
}
ASMJIT_INLINE
Link
*
getFirst
()
const
{
return
_first
;
}
ASMJIT_INLINE
Link
*
getLast
()
const
{
return
_last
;
}
// --------------------------------------------------------------------------
// [Ops]
// --------------------------------------------------------------------------
ASMJIT_INLINE
void
reset
()
{
_first
=
NULL
;
_last
=
NULL
;
}
ASMJIT_INLINE
void
prepend
(
Link
*
link
)
{
link
->
_next
=
_first
;
if
(
_first
==
NULL
)
_last
=
link
;
_first
=
link
;
}
ASMJIT_INLINE
void
append
(
Link
*
link
)
{
link
->
_next
=
NULL
;
if
(
_first
==
NULL
)
_first
=
link
;
else
_last
->
_next
=
link
;
_last
=
link
;
}
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
Link
*
_first
;
Link
*
_last
;
};
//! \}
}
// asmjit namespace
// [Api-End]
#include "../apiend.h"
// [Guard]
#endif // _ASMJIT_BASE_CONTAINERS_H
libraries/asmjit/base/context.cpp
0 → 100644
View file @
61d5cc0f
// [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_DISABLE_COMPILER)
// [Dependencies - AsmJit]
#include "../base/context_p.h"
#include "../base/intutil.h"
// [Api-Begin]
#include "../apibegin.h"
namespace
asmjit
{
// ============================================================================
// [asmjit::Context - Construction / Destruction]
// ============================================================================
Context
::
Context
(
Compiler
*
compiler
)
:
_compiler
(
compiler
),
_baseZone
(
8192
-
kZoneOverhead
),
_varMapToVaListOffset
(
0
)
{
Context
::
reset
();
}
Context
::~
Context
()
{}
// ============================================================================
// [asmjit::Context - Reset]
// ============================================================================
void
Context
::
reset
(
bool
releaseMemory
)
{
_baseZone
.
reset
(
releaseMemory
);
_func
=
NULL
;
_start
=
NULL
;
_end
=
NULL
;
_extraBlock
=
NULL
;
_stop
=
NULL
;
_unreachableList
.
reset
();
_jccList
.
reset
();
_contextVd
.
reset
(
releaseMemory
);
_memVarCells
=
NULL
;
_memStackCells
=
NULL
;
_mem1ByteVarsUsed
=
0
;
_mem2ByteVarsUsed
=
0
;
_mem4ByteVarsUsed
=
0
;
_mem8ByteVarsUsed
=
0
;
_mem16ByteVarsUsed
=
0
;
_mem32ByteVarsUsed
=
0
;
_mem64ByteVarsUsed
=
0
;
_memStackCellsUsed
=
0
;
_memMaxAlign
=
0
;
_memVarTotal
=
0
;
_memStackTotal
=
0
;
_memAllTotal
=
0
;
_annotationLength
=
12
;
_state
=
NULL
;
}
// ============================================================================
// [asmjit::Context - Mem]
// ============================================================================
static
ASMJIT_INLINE
uint32_t
BaseContext_getDefaultAlignment
(
uint32_t
size
)
{
if
(
size
>
32
)
return
64
;
else
if
(
size
>
16
)
return
32
;
else
if
(
size
>
8
)
return
16
;
else
if
(
size
>
4
)
return
8
;
else
if
(
size
>
2
)
return
4
;
else
if
(
size
>
1
)
return
2
;
else
return
1
;
}
MemCell
*
Context
::
_newVarCell
(
VarData
*
vd
)
{
ASMJIT_ASSERT
(
vd
->
_memCell
==
NULL
);
MemCell
*
cell
;
uint32_t
size
=
vd
->
getSize
();
if
(
vd
->
isStack
())
{
cell
=
_newStackCell
(
size
,
vd
->
getAlignment
());
if
(
cell
==
NULL
)
return
NULL
;
}
else
{
cell
=
static_cast
<
MemCell
*>
(
_baseZone
.
alloc
(
sizeof
(
MemCell
)));
if
(
cell
==
NULL
)
goto
_NoMemory
;
cell
->
_next
=
_memVarCells
;
_memVarCells
=
cell
;
cell
->
_offset
=
0
;
cell
->
_size
=
size
;
cell
->
_alignment
=
size
;
_memMaxAlign
=
IntUtil
::
iMax
<
uint32_t
>
(
_memMaxAlign
,
size
);
_memVarTotal
+=
size
;
switch
(
size
)
{
case
1
:
_mem1ByteVarsUsed
++
;
break
;
case
2
:
_mem2ByteVarsUsed
++
;
break
;
case
4
:
_mem4ByteVarsUsed
++
;
break
;
case
8
:
_mem8ByteVarsUsed
++
;
break
;
case
16
:
_mem16ByteVarsUsed
++
;
break
;
case
32
:
_mem32ByteVarsUsed
++
;
break
;
case
64
:
_mem64ByteVarsUsed
++
;
break
;
default:
ASMJIT_ASSERT
(
!
"Reached"
);
}
}
vd
->
_memCell
=
cell
;
return
cell
;
_NoMemory:
_compiler
->
setError
(
kErrorNoHeapMemory
);
return
NULL
;
}
MemCell
*
Context
::
_newStackCell
(
uint32_t
size
,
uint32_t
alignment
)
{
MemCell
*
cell
=
static_cast
<
MemCell
*>
(
_baseZone
.
alloc
(
sizeof
(
MemCell
)));
if
(
cell
==
NULL
)
goto
_NoMemory
;
if
(
alignment
==
0
)
alignment
=
BaseContext_getDefaultAlignment
(
size
);
if
(
alignment
>
64
)
alignment
=
64
;
ASMJIT_ASSERT
(
IntUtil
::
isPowerOf2
(
alignment
));
size
=
IntUtil
::
alignTo
<
uint32_t
>
(
size
,
alignment
);
// Insert it sorted according to the alignment and size.
{
MemCell
**
pPrev
=
&
_memStackCells
;
MemCell
*
cur
=
*
pPrev
;
for
(
cur
=
*
pPrev
;
cur
!=
NULL
;
cur
=
cur
->
_next
)
{
if
(
cur
->
getAlignment
()
>
alignment
)
continue
;
if
(
cur
->
getAlignment
()
==
alignment
&&
cur
->
getSize
()
>
size
)
continue
;
break
;
}
cell
->
_next
=
cur
;
cell
->
_offset
=
0
;
cell
->
_size
=
size
;
cell
->
_alignment
=
alignment
;
*
pPrev
=
cell
;
_memStackCellsUsed
++
;
_memMaxAlign
=
IntUtil
::
iMax
<
uint32_t
>
(
_memMaxAlign
,
alignment
);
_memStackTotal
+=
size
;
}
return
cell
;
_NoMemory:
_compiler
->
setError
(
kErrorNoHeapMemory
);
return
NULL
;
}
Error
Context
::
resolveCellOffsets
()
{
MemCell
*
varCell
=
_memVarCells
;
MemCell
*
stackCell
=
_memStackCells
;
uint32_t
stackAlignment
=
0
;
if
(
stackCell
!=
NULL
)
stackAlignment
=
stackCell
->
getAlignment
();
uint32_t
pos64
=
0
;
uint32_t
pos32
=
pos64
+
_mem64ByteVarsUsed
*
64
;
uint32_t
pos16
=
pos32
+
_mem32ByteVarsUsed
*
32
;
uint32_t
pos8
=
pos16
+
_mem16ByteVarsUsed
*
16
;
uint32_t
pos4
=
pos8
+
_mem8ByteVarsUsed
*
8
;
uint32_t
pos2
=
pos4
+
_mem4ByteVarsUsed
*
4
;
uint32_t
pos1
=
pos2
+
_mem2ByteVarsUsed
*
2
;
uint32_t
stackPos
=
pos1
+
_mem1ByteVarsUsed
;
uint32_t
gapAlignment
=
stackAlignment
;
uint32_t
gapSize
=
0
;
if
(
gapAlignment
)
IntUtil
::
deltaTo
(
stackPos
,
gapAlignment
);
stackPos
+=
gapSize
;
uint32_t
gapPos
=
stackPos
;
uint32_t
allTotal
=
stackPos
;
// Vars - Allocated according to alignment/width.
while
(
varCell
!=
NULL
)
{
uint32_t
size
=
varCell
->
getSize
();
uint32_t
offset
=
0
;
switch
(
size
)
{
case
1
:
offset
=
pos1
;
pos1
+=
1
;
break
;
case
2
:
offset
=
pos2
;
pos2
+=
2
;
break
;
case
4
:
offset
=
pos4
;
pos4
+=
4
;
break
;
case
8
:
offset
=
pos8
;
pos8
+=
8
;
break
;
case
16
:
offset
=
pos16
;
pos16
+=
16
;
break
;
case
32
:
offset
=
pos32
;
pos32
+=
32
;
break
;
case
64
:
offset
=
pos64
;
pos64
+=
64
;
break
;
default:
ASMJIT_ASSERT
(
!
"Reached"
);
}
varCell
->
setOffset
(
static_cast
<
int32_t
>
(
offset
));
varCell
=
varCell
->
_next
;
}
// Stack - Allocated according to alignment/width.
while
(
stackCell
!=
NULL
)
{
uint32_t
size
=
stackCell
->
getSize
();
uint32_t
alignment
=
stackCell
->
getAlignment
();
uint32_t
offset
;
// Try to fill the gap between variables/stack first.
if
(
size
<=
gapSize
&&
alignment
<=
gapAlignment
)
{
offset
=
gapPos
;
gapSize
-=
size
;
gapPos
-=
size
;
if
(
alignment
<
gapAlignment
)
gapAlignment
=
alignment
;
}
else
{
offset
=
stackPos
;
stackPos
+=
size
;
allTotal
+=
size
;
}
stackCell
->
setOffset
(
offset
);
stackCell
=
stackCell
->
_next
;
}
_memAllTotal
=
allTotal
;
return
kErrorOk
;
}
// ============================================================================
// [asmjit::Context - RemoveUnreachableCode]
// ============================================================================
Error
Context
::
removeUnreachableCode
()
{
PodList
<
Node
*>::
Link
*
link
=
_unreachableList
.
getFirst
();
Node
*
stop
=
getStop
();
while
(
link
!=
NULL
)
{
Node
*
node
=
link
->
getValue
();
if
(
node
!=
NULL
&&
node
->
getPrev
()
!=
NULL
)
{
// Locate all unreachable nodes.
Node
*
first
=
node
;
do
{
if
(
node
->
isFetched
())
break
;
node
=
node
->
getNext
();
}
while
(
node
!=
stop
);
// Remove.
if
(
node
!=
first
)
{
Node
*
last
=
(
node
!=
NULL
)
?
node
->
getPrev
()
:
getCompiler
()
->
getLastNode
();
getCompiler
()
->
removeNodes
(
first
,
last
);
}
}
link
=
link
->
getNext
();
}
return
kErrorOk
;
}
// ============================================================================
// [asmjit::Context - Liveness Analysis]
// ============================================================================
//! \internal
struct
LivenessTarget
{
//! Previous target.
LivenessTarget
*
prev
;
//! Target node.
TargetNode
*
node
;
//! Jumped from.
JumpNode
*
from
;
};
Error
Context
::
livenessAnalysis
()
{
FuncNode
*
func
=
getFunc
();
JumpNode
*
from
=
NULL
;
Node
*
node
=
func
->
getEnd
();
uint32_t
bLen
=
static_cast
<
uint32_t
>
(
((
_contextVd
.
getLength
()
+
VarBits
::
kEntityBits
-
1
)
/
VarBits
::
kEntityBits
));
LivenessTarget
*
ltCur
=
NULL
;
LivenessTarget
*
ltUnused
=
NULL
;
size_t
varMapToVaListOffset
=
_varMapToVaListOffset
;
// No variables.
if
(
bLen
==
0
)
return
kErrorOk
;
VarBits
*
bCur
=
newBits
(
bLen
);
if
(
bCur
==
NULL
)
goto
_NoMemory
;
// Allocate bits for code visited first time.
_OnVisit:
for
(;;)
{
if
(
node
->
hasLiveness
())
{
if
(
bCur
->
_addBitsDelSource
(
node
->
getLiveness
(),
bCur
,
bLen
))
goto
_OnPatch
;
else
goto
_OnDone
;
}
VarBits
*
bTmp
=
copyBits
(
bCur
,
bLen
);
if
(
bTmp
==
NULL
)
goto
_NoMemory
;
node
->
setLiveness
(
bTmp
);
VarMap
*
map
=
node
->
getMap
();
if
(
map
!=
NULL
)
{
uint32_t
vaCount
=
map
->
getVaCount
();
VarAttr
*
vaList
=
reinterpret_cast
<
VarAttr
*>
(((
uint8_t
*
)
map
)
+
varMapToVaListOffset
);
for
(
uint32_t
i
=
0
;
i
<
vaCount
;
i
++
)
{
VarAttr
*
va
=
&
vaList
[
i
];
VarData
*
vd
=
va
->
getVd
();
uint32_t
flags
=
va
->
getFlags
();
uint32_t
ctxId
=
vd
->
getContextId
();
if
((
flags
&
kVarAttrOutAll
)
&&
!
(
flags
&
kVarAttrInAll
))
{
// Write-Only.
bTmp
->
setBit
(
ctxId
);
bCur
->
delBit
(
ctxId
);
}
else
{
// Read-Only or Read/Write.
bTmp
->
setBit
(
ctxId
);
bCur
->
setBit
(
ctxId
);
}
}
}
if
(
node
->
getType
()
==
kNodeTypeTarget
)
goto
_OnTarget
;
if
(
node
==
func
)
goto
_OnDone
;
ASMJIT_ASSERT
(
node
->
getPrev
());
node
=
node
->
getPrev
();
}
// Patch already generated liveness bits.
_OnPatch:
for
(;;)
{
ASMJIT_ASSERT
(
node
->
hasLiveness
());
VarBits
*
bNode
=
node
->
getLiveness
();
if
(
!
bNode
->
_addBitsDelSource
(
bCur
,
bLen
))
goto
_OnDone
;
if
(
node
->
getType
()
==
kNodeTypeTarget
)
goto
_OnTarget
;
if
(
node
==
func
)
goto
_OnDone
;
node
=
node
->
getPrev
();
}
_OnTarget:
if
(
static_cast
<
TargetNode
*>
(
node
)
->
getNumRefs
()
!=
0
)
{
// Push a new LivenessTarget onto the stack if needed.
if
(
ltCur
==
NULL
||
ltCur
->
node
!=
node
)
{
// Allocate a new LivenessTarget object (from pool or zone).
LivenessTarget
*
ltTmp
=
ltUnused
;
if
(
ltTmp
!=
NULL
)
{
ltUnused
=
ltUnused
->
prev
;
}
else
{
ltTmp
=
_baseZone
.
allocT
<
LivenessTarget
>
(
sizeof
(
LivenessTarget
)
-
sizeof
(
VarBits
)
+
bLen
*
sizeof
(
uintptr_t
));
if
(
ltTmp
==
NULL
)
goto
_NoMemory
;
}
// Initialize and make current - ltTmp->from will be set later on.
ltTmp
->
prev
=
ltCur
;
ltTmp
->
node
=
static_cast
<
TargetNode
*>
(
node
);
ltCur
=
ltTmp
;
from
=
static_cast
<
TargetNode
*>
(
node
)
->
getFrom
();
ASMJIT_ASSERT
(
from
!=
NULL
);
}
else
{
from
=
ltCur
->
from
;
goto
_OnJumpNext
;
}
// Visit/Patch.
do
{
ltCur
->
from
=
from
;
bCur
->
copyBits
(
node
->
getLiveness
(),
bLen
);
if
(
!
from
->
hasLiveness
())
{
node
=
from
;
goto
_OnVisit
;
}
// Issue #25: Moved '_OnJumpNext' here since it's important to patch
// code again if there are more live variables than before.
_OnJumpNext:
if
(
bCur
->
delBits
(
from
->
getLiveness
(),
bLen
))
{
node
=
from
;
goto
_OnPatch
;
}
from
=
from
->
getJumpNext
();
}
while
(
from
!=
NULL
);
// Pop the current LivenessTarget from the stack.
{
LivenessTarget
*
ltTmp
=
ltCur
;
ltCur
=
ltCur
->
prev
;
ltTmp
->
prev
=
ltUnused
;
ltUnused
=
ltTmp
;
}
}
bCur
->
copyBits
(
node
->
getLiveness
(),
bLen
);
node
=
node
->
getPrev
();
if
(
node
->
isJmp
()
||
!
node
->
isFetched
())
goto
_OnDone
;
if
(
!
node
->
hasLiveness
())
goto
_OnVisit
;
if
(
bCur
->
delBits
(
node
->
getLiveness
(),
bLen
))
goto
_OnPatch
;
_OnDone:
if
(
ltCur
!=
NULL
)
{
node
=
ltCur
->
node
;
from
=
ltCur
->
from
;
goto
_OnJumpNext
;
}
return
kErrorOk
;
_NoMemory:
return
setError
(
kErrorNoHeapMemory
);
}
// ============================================================================
// [asmjit::Context - Schedule]
// ============================================================================
Error
Context
::
schedule
()
{
// By default there is no instruction scheduler implemented.
return
kErrorOk
;
}
// ============================================================================
// [asmjit::Context - Cleanup]
// ============================================================================
void
Context
::
cleanup
()
{
VarData
**
array
=
_contextVd
.
getData
();
size_t
length
=
_contextVd
.
getLength
();
for
(
size_t
i
=
0
;
i
<
length
;
i
++
)
{
VarData
*
vd
=
array
[
i
];
vd
->
resetContextId
();
vd
->
resetRegIndex
();
}
_contextVd
.
reset
(
false
);
_extraBlock
=
NULL
;
}
// ============================================================================
// [asmjit::Context - CompileFunc]
// ============================================================================
Error
Context
::
compile
(
FuncNode
*
func
)
{
Node
*
end
=
func
->
getEnd
();
Node
*
stop
=
end
->
getNext
();
_func
=
func
;
_stop
=
stop
;
_extraBlock
=
end
;
ASMJIT_PROPAGATE_ERROR
(
fetch
());
ASMJIT_PROPAGATE_ERROR
(
removeUnreachableCode
());
ASMJIT_PROPAGATE_ERROR
(
livenessAnalysis
());
Compiler
*
compiler
=
getCompiler
();
#if !defined(ASMJIT_DISABLE_LOGGER)
if
(
compiler
->
hasLogger
())
ASMJIT_PROPAGATE_ERROR
(
annotate
());
#endif // !ASMJIT_DISABLE_LOGGER
ASMJIT_PROPAGATE_ERROR
(
translate
());
if
(
compiler
->
hasFeature
(
kCodeGenEnableScheduler
))
ASMJIT_PROPAGATE_ERROR
(
schedule
());
// We alter the compiler cursor, because it doesn't make sense to reference
// it after compilation - some nodes may disappear and it's forbidden to add
// new code after the compilation is done.
compiler
->
_setCursor
(
NULL
);
return
kErrorOk
;
}
}
// asmjit namespace
// [Api-End]
#include "../apiend.h"
// [Guard]
#endif // !ASMJIT_DISABLE_COMPILER
libraries/asmjit/base/context_p.h
0 → 100644
View file @
61d5cc0f
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Guard]
#ifndef _ASMJIT_BASE_CONTEXT_P_H
#define _ASMJIT_BASE_CONTEXT_P_H
#include "../build.h"
#if !defined(ASMJIT_DISABLE_COMPILER)
// [Dependencies - AsmJit]
#include "../base/compiler.h"
#include "../base/zone.h"
// [Api-Begin]
#include "../apibegin.h"
namespace
asmjit
{
//! \addtogroup asmjit_base_compiler
//! \{
// ============================================================================
// [asmjit::Context]
// ============================================================================
//! \internal
//!
//! Code generation context is the logic behind `Compiler`. The context is
//! used to compile the code stored in `Compiler`.
struct
Context
{
ASMJIT_NO_COPY
(
Context
)
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
Context
(
Compiler
*
compiler
);
virtual
~
Context
();
// --------------------------------------------------------------------------
// [Reset]
// --------------------------------------------------------------------------
//! Reset the whole context.
virtual
void
reset
(
bool
releaseMemory
=
false
);
// --------------------------------------------------------------------------
// [Accessors]
// --------------------------------------------------------------------------
//! Get compiler.
ASMJIT_INLINE
Compiler
*
getCompiler
()
const
{
return
_compiler
;
}
//! Get function.
ASMJIT_INLINE
FuncNode
*
getFunc
()
const
{
return
_func
;
}
//! Get stop node.
ASMJIT_INLINE
Node
*
getStop
()
const
{
return
_stop
;
}
//! Get start of the current scope.
ASMJIT_INLINE
Node
*
getStart
()
const
{
return
_start
;
}
//! Get end of the current scope.
ASMJIT_INLINE
Node
*
getEnd
()
const
{
return
_end
;
}
//! Get extra block.
ASMJIT_INLINE
Node
*
getExtraBlock
()
const
{
return
_extraBlock
;
}
//! Set extra block.
ASMJIT_INLINE
void
setExtraBlock
(
Node
*
node
)
{
_extraBlock
=
node
;
}
// --------------------------------------------------------------------------
// [Error]
// --------------------------------------------------------------------------
//! Get the last error code.
ASMJIT_INLINE
Error
getError
()
const
{
return
getCompiler
()
->
getError
();
}
//! Set the last error code and propagate it through the error handler.
ASMJIT_INLINE
Error
setError
(
Error
error
,
const
char
*
message
=
NULL
)
{
return
getCompiler
()
->
setError
(
error
,
message
);
}
// --------------------------------------------------------------------------
// [State]
// --------------------------------------------------------------------------
//! Get current state.
ASMJIT_INLINE
VarState
*
getState
()
const
{
return
_state
;
}
//! Load current state from `target` state.
virtual
void
loadState
(
VarState
*
src
)
=
0
;
//! Save current state, returning new `VarState` instance.
virtual
VarState
*
saveState
()
=
0
;
//! Change the current state to `target` state.
virtual
void
switchState
(
VarState
*
src
)
=
0
;
//! Change the current state to the intersection of two states `a` and `b`.
virtual
void
intersectStates
(
VarState
*
a
,
VarState
*
b
)
=
0
;
// --------------------------------------------------------------------------
// [Context]
// --------------------------------------------------------------------------
ASMJIT_INLINE
Error
_registerContextVar
(
VarData
*
vd
)
{
if
(
vd
->
hasContextId
())
return
kErrorOk
;
uint32_t
cid
=
static_cast
<
uint32_t
>
(
_contextVd
.
getLength
());
ASMJIT_PROPAGATE_ERROR
(
_contextVd
.
append
(
vd
));
vd
->
setContextId
(
cid
);
return
kErrorOk
;
}
// --------------------------------------------------------------------------
// [Mem]
// --------------------------------------------------------------------------
MemCell
*
_newVarCell
(
VarData
*
vd
);
MemCell
*
_newStackCell
(
uint32_t
size
,
uint32_t
alignment
);
ASMJIT_INLINE
MemCell
*
getVarCell
(
VarData
*
vd
)
{
MemCell
*
cell
=
vd
->
getMemCell
();
return
cell
?
cell
:
_newVarCell
(
vd
);
}
virtual
Error
resolveCellOffsets
();
// --------------------------------------------------------------------------
// [Bits]
// --------------------------------------------------------------------------
ASMJIT_INLINE
VarBits
*
newBits
(
uint32_t
len
)
{
return
static_cast
<
VarBits
*>
(
_baseZone
.
allocZeroed
(
static_cast
<
size_t
>
(
len
)
*
VarBits
::
kEntitySize
));
}
ASMJIT_INLINE
VarBits
*
copyBits
(
const
VarBits
*
src
,
uint32_t
len
)
{
return
static_cast
<
VarBits
*>
(
_baseZone
.
dup
(
src
,
static_cast
<
size_t
>
(
len
)
*
VarBits
::
kEntitySize
));
}
// --------------------------------------------------------------------------
// [Fetch]
// --------------------------------------------------------------------------
//! Fetch.
//!
//! Fetch iterates over all nodes and gathers information about all variables
//! used. The process generates information required by register allocator,
//! variable liveness analysis and translator.
virtual
Error
fetch
()
=
0
;
// --------------------------------------------------------------------------
// [RemoveUnreachableCode]
// --------------------------------------------------------------------------
//! Remove unreachable code.
virtual
Error
removeUnreachableCode
();
// --------------------------------------------------------------------------
// [Analyze]
// --------------------------------------------------------------------------
//! Perform variable liveness analysis.
//!
//! Analysis phase iterates over nodes in reverse order and generates a bit
//! array describing variables that are alive at every node in the function.
//! When the analysis start all variables are assumed dead. When a read or
//! read/write operations of a variable is detected the variable becomes
//! alive; when only write operation is detected the variable becomes dead.
//!
//! When a label is found all jumps to that label are followed and analysis
//! repeats until all variables are resolved.
virtual
Error
livenessAnalysis
();
// --------------------------------------------------------------------------
// [Annotate]
// --------------------------------------------------------------------------
virtual
Error
annotate
()
=
0
;
// --------------------------------------------------------------------------
// [Translate]
// --------------------------------------------------------------------------
//! Translate code by allocating registers and handling state changes.
virtual
Error
translate
()
=
0
;
// --------------------------------------------------------------------------
// [Schedule]
// --------------------------------------------------------------------------
virtual
Error
schedule
();
// --------------------------------------------------------------------------
// [Cleanup]
// --------------------------------------------------------------------------
virtual
void
cleanup
();
// --------------------------------------------------------------------------
// [Compile]
// --------------------------------------------------------------------------
virtual
Error
compile
(
FuncNode
*
func
);
// --------------------------------------------------------------------------
// [Serialize]
// --------------------------------------------------------------------------
virtual
Error
serialize
(
Assembler
*
assembler
,
Node
*
start
,
Node
*
stop
)
=
0
;
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
//! Compiler.
Compiler
*
_compiler
;
//! Function.
FuncNode
*
_func
;
//! Zone allocator.
Zone
_baseZone
;
//! \internal
//!
//! Offset (how many bytes to add) to `VarMap` to get `VarAttr` array. Used
//! by liveness analysis shared across all backends. This is needed because
//! `VarMap` is a base class for a specialized version that liveness analysis
//! doesn't use, it just needs `VarAttr` array.
uint32_t
_varMapToVaListOffset
;
//! Start of the current active scope.
Node
*
_start
;
//! End of the current active scope.
Node
*
_end
;
//! Node that is used to insert extra code after the function body.
Node
*
_extraBlock
;
//! Stop node.
Node
*
_stop
;
//! Unreachable nodes.
PodList
<
Node
*>
_unreachableList
;
//! Jump nodes.
PodList
<
Node
*>
_jccList
;
//! All variables used by the current function.
PodVector
<
VarData
*>
_contextVd
;
//! Memory used to spill variables.
MemCell
*
_memVarCells
;
//! Memory used to alloc memory on the stack.
MemCell
*
_memStackCells
;
//! Count of 1-byte cells.
uint32_t
_mem1ByteVarsUsed
;
//! Count of 2-byte cells.
uint32_t
_mem2ByteVarsUsed
;
//! Count of 4-byte cells.
uint32_t
_mem4ByteVarsUsed
;
//! Count of 8-byte cells.
uint32_t
_mem8ByteVarsUsed
;
//! Count of 16-byte cells.
uint32_t
_mem16ByteVarsUsed
;
//! Count of 32-byte cells.
uint32_t
_mem32ByteVarsUsed
;
//! Count of 64-byte cells.
uint32_t
_mem64ByteVarsUsed
;
//! Count of stack memory cells.
uint32_t
_memStackCellsUsed
;
//! Maximum memory alignment used by the function.
uint32_t
_memMaxAlign
;
//! Count of bytes used by variables.
uint32_t
_memVarTotal
;
//! Count of bytes used by stack.
uint32_t
_memStackTotal
;
//! Count of bytes used by variables and stack after alignment.
uint32_t
_memAllTotal
;
//! Default lenght of annotated instruction.
uint32_t
_annotationLength
;
//! Current state (used by register allocator).
VarState
*
_state
;
};
//! \}
}
// asmjit namespace
// [Api-End]
#include "../apiend.h"
// [Guard]
#endif // !ASMJIT_DISABLE_COMPILER
#endif // _ASMJIT_BASE_CONTEXT_P_H
libraries/asmjit/base/cpuinfo.cpp
0 → 100644
View file @
61d5cc0f
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Export]
#define ASMJIT_EXPORTS
// [Dependencies - AsmJit]
#include "../base/cpuinfo.h"
#if defined(ASMJIT_ARCH_X86) || defined(ASMJIT_ARCH_X64)
#include "../x86/x86cpuinfo.h"
#else
// ?
#endif
// [Dependencies - Posix]
#if defined(ASMJIT_OS_POSIX)
# include <errno.h>
# include <sys/statvfs.h>
# include <sys/utsname.h>
# include <unistd.h>
#endif // ASMJIT_OS_POSIX
// [Api-Begin]
#include "../apibegin.h"
namespace
asmjit
{
// ============================================================================
// [asmjit::CpuInfo - DetectHwThreadsCount]
// ============================================================================
uint32_t
CpuInfo
::
detectHwThreadsCount
()
{
#if defined(ASMJIT_OS_WINDOWS)
SYSTEM_INFO
info
;
::
GetSystemInfo
(
&
info
);
return
info
.
dwNumberOfProcessors
;
#elif defined(ASMJIT_OS_POSIX) && defined(_SC_NPROCESSORS_ONLN)
// It seems that sysconf returns the number of "logical" processors on both
// mac and linux. So we get the number of "online logical" processors.
long
res
=
::
sysconf
(
_SC_NPROCESSORS_ONLN
);
if
(
res
==
-
1
)
return
1
;
return
static_cast
<
uint32_t
>
(
res
);
#else
return
1
;
#endif
}
// ============================================================================
// [asmjit::CpuInfo - GetHost]
// ============================================================================
#if defined(ASMJIT_ARCH_X86) || defined(ASMJIT_ARCH_X64)
struct
AutoX86CpuInfo
:
public
X86CpuInfo
{
ASMJIT_INLINE
AutoX86CpuInfo
()
:
X86CpuInfo
()
{
X86CpuUtil
::
detect
(
this
);
}
};
#else
#error "AsmJit - Unsupported CPU."
#endif
const
CpuInfo
*
CpuInfo
::
getHost
()
{
#if defined(ASMJIT_ARCH_X86) || defined(ASMJIT_ARCH_X64)
static
AutoX86CpuInfo
cpuInfo
;
#else
#error "AsmJit - Unsupported CPU."
#endif
return
&
cpuInfo
;
}
}
// asmjit namespace
// [Api-End]
#include "../apiend.h"
libraries/asmjit/base/cpuinfo.h
0 → 100644
View file @
61d5cc0f
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Guard]
#ifndef _ASMJIT_BASE_CPUINFO_H
#define _ASMJIT_BASE_CPUINFO_H
// [Dependencies - AsmJit]
#include "../base/globals.h"
// [Api-Begin]
#include "../apibegin.h"
namespace
asmjit
{
//! \addtogroup asmjit_base_general
//! \{
// ============================================================================
// [asmjit::CpuVendor]
// ============================================================================
//! Cpu vendor ID.
//!
//! 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
(
CpuVendor
)
{
//! No/Unknown vendor.
kCpuVendorNone
=
0
,
//! Intel vendor.
kCpuVendorIntel
=
1
,
//! AMD vendor.
kCpuVendorAmd
=
2
,
//! VIA vendor.
kCpuVendorVia
=
3
};
// ============================================================================
// [asmjit::CpuInfo]
// ============================================================================
//! Base cpu information.
struct
CpuInfo
{
ASMJIT_NO_COPY
(
CpuInfo
)
//! \internal
enum
{
kFeaturesPerUInt32
=
static_cast
<
int
>
(
sizeof
(
uint32_t
))
*
8
};
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
ASMJIT_INLINE
CpuInfo
(
uint32_t
size
)
:
_size
(
size
)
{}
// --------------------------------------------------------------------------
// [Accessors]
// --------------------------------------------------------------------------
//! Get CPU vendor string.
ASMJIT_INLINE
const
char
*
getVendorString
()
const
{
return
_vendorString
;
}
//! Get CPU brand string.
ASMJIT_INLINE
const
char
*
getBrandString
()
const
{
return
_brandString
;
}
//! Get CPU vendor ID.
ASMJIT_INLINE
uint32_t
getVendorId
()
const
{
return
_vendorId
;
}
//! Get CPU family ID.
ASMJIT_INLINE
uint32_t
getFamily
()
const
{
return
_family
;
}
//! Get CPU model ID.
ASMJIT_INLINE
uint32_t
getModel
()
const
{
return
_model
;
}
//! Get CPU stepping.
ASMJIT_INLINE
uint32_t
getStepping
()
const
{
return
_stepping
;
}
//! Get number of hardware threads available.
ASMJIT_INLINE
uint32_t
getHwThreadsCount
()
const
{
return
_hwThreadsCount
;
}
//! Get whether CPU has a `feature`.
ASMJIT_INLINE
bool
hasFeature
(
uint32_t
feature
)
const
{
ASMJIT_ASSERT
(
feature
<
sizeof
(
_features
)
*
8
);
return
static_cast
<
bool
>
(
(
_features
[
feature
/
kFeaturesPerUInt32
]
>>
(
feature
%
kFeaturesPerUInt32
))
&
0x1
);
}
//! Add a CPU `feature`.
ASMJIT_INLINE
CpuInfo
&
addFeature
(
uint32_t
feature
)
{
ASMJIT_ASSERT
(
feature
<
sizeof
(
_features
)
*
8
);
_features
[
feature
/
kFeaturesPerUInt32
]
|=
(
1U
<<
(
feature
%
kFeaturesPerUInt32
));
return
*
this
;
}
// --------------------------------------------------------------------------
// [Statics]
// --------------------------------------------------------------------------
//! Detect the number of hardware threads.
static
ASMJIT_API
uint32_t
detectHwThreadsCount
();
//! Get host cpu.
static
ASMJIT_API
const
CpuInfo
*
getHost
();
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
//! Size of the structure in bytes.
uint32_t
_size
;
//! Cpu short vendor string.
char
_vendorString
[
16
];
//! Cpu long vendor string (brand).
char
_brandString
[
64
];
//! Cpu vendor id, see \ref CpuVendor.
uint32_t
_vendorId
;
//! Cpu family ID.
uint32_t
_family
;
//! Cpu model ID.
uint32_t
_model
;
//! Cpu stepping.
uint32_t
_stepping
;
//! Number of hardware threads.
uint32_t
_hwThreadsCount
;
//! Cpu features bitfield.
uint32_t
_features
[
4
];
};
//! \}
}
// asmjit namespace
// [Api-End]
#include "../apiend.h"
// [Guard]
#endif // _ASMJIT_BASE_CPUINFO_H
libraries/asmjit/base/cputicks.cpp
0 → 100644
View file @
61d5cc0f
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Export]
#define ASMJIT_EXPORTS
// [Dependencies - AsmJit]
#include "../base/cputicks.h"
// [Dependencies - Posix]
#if defined(ASMJIT_OS_POSIX)
# include <time.h>
# include <unistd.h>
#endif // ASMJIT_OS_POSIX
// [Dependencies - Mac]
#if defined(ASMJIT_OS_MAC)
# include <mach/mach_time.h>
#endif // ASMJIT_OS_MAC
// [Dependencies - Windows]
#if defined(ASMJIT_OS_WINDOWS)
// `_InterlockedCompareExchange` is only available as intrinsic (MS Compiler).
# if defined(_MSC_VER) && _MSC_VER >= 1400
# include <intrin.h>
# pragma intrinsic(_InterlockedCompareExchange)
# else
# define _InterlockedCompareExchange InterlockedCompareExchange
# endif // _MSC_VER
#endif // ASMJIT_OS_WINDOWS
// [Api-Begin]
#include "../apibegin.h"
namespace
asmjit
{
// ============================================================================
// [asmjit::CpuTicks - Windows]
// ============================================================================
#if defined(ASMJIT_OS_WINDOWS)
static
volatile
uint32_t
CpuTicks_hiResOk
;
static
volatile
double
CpuTicks_hiResFreq
;
uint32_t
CpuTicks
::
now
()
{
do
{
uint32_t
hiResOk
=
CpuTicks_hiResOk
;
if
(
hiResOk
==
1
)
{
LARGE_INTEGER
now
;
if
(
!::
QueryPerformanceCounter
(
&
now
))
break
;
return
(
int64_t
)(
double
(
now
.
QuadPart
)
/
CpuTicks_hiResFreq
);
}
if
(
hiResOk
==
0
)
{
LARGE_INTEGER
qpf
;
if
(
!::
QueryPerformanceFrequency
(
&
qpf
))
{
_InterlockedCompareExchange
((
LONG
*
)
&
CpuTicks_hiResOk
,
0xFFFFFFFF
,
0
);
break
;
}
LARGE_INTEGER
now
;
if
(
!::
QueryPerformanceCounter
(
&
now
))
{
_InterlockedCompareExchange
((
LONG
*
)
&
CpuTicks_hiResOk
,
0xFFFFFFFF
,
0
);
break
;
}
double
freqDouble
=
double
(
qpf
.
QuadPart
)
/
1000.0
;
CpuTicks_hiResFreq
=
freqDouble
;
_InterlockedCompareExchange
((
LONG
*
)
&
CpuTicks_hiResOk
,
1
,
0
);
return
static_cast
<
uint32_t
>
(
static_cast
<
int64_t
>
(
double
(
now
.
QuadPart
)
/
freqDouble
)
&
0xFFFFFFFF
);
}
}
while
(
0
);
// Bail to a less precise GetTickCount().
return
::
GetTickCount
();
}
// ============================================================================
// [asmjit::CpuTicks - Mac]
// ============================================================================
#elif defined(ASMJIT_OS_MAC)
static
mach_timebase_info_data_t
CpuTicks_machTime
;
uint32_t
CpuTicks
::
now
()
{
// Initialize the first time CpuTicks::now() is called (See Apple's QA1398).
if
(
CpuTicks_machTime
.
denom
==
0
)
{
if
(
mach_timebase_info
(
&
CpuTicks_machTime
)
!=
KERN_SUCCESS
);
return
0
;
}
// mach_absolute_time() returns nanoseconds, we need just milliseconds.
uint64_t
t
=
mach_absolute_time
()
/
1000000
;
t
=
t
*
CpuTicks_machTime
.
numer
/
CpuTicks_machTime
.
denom
;
return
static_cast
<
uint32_t
>
(
t
&
0xFFFFFFFFU
);
}
// ============================================================================
// [asmjit::CpuTicks - Posix]
// ============================================================================
#else
uint32_t
CpuTicks
::
now
()
{
#if defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0
struct
timespec
ts
;
if
(
clock_gettime
(
CLOCK_MONOTONIC
,
&
ts
)
!=
0
)
return
0
;
uint64_t
t
=
(
uint64_t
(
ts
.
tv_sec
)
*
1000
)
+
(
uint64_t
(
ts
.
tv_nsec
)
/
1000000
);
return
static_cast
<
uint32_t
>
(
t
&
0xFFFFFFFFU
);
#else // _POSIX_MONOTONIC_CLOCK
#error "AsmJit - Unsupported OS."
return
0
;
#endif // _POSIX_MONOTONIC_CLOCK
}
#endif // ASMJIT_OS
}
// asmjit namespace
// [Api-End]
#include "../apiend.h"
libraries/asmjit/base/cputicks.h
0 → 100644
View file @
61d5cc0f
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Guard]
#ifndef _ASMJIT_BASE_CPUTICKS_H
#define _ASMJIT_BASE_CPUTICKS_H
// [Dependencies - AsmJit]
#include "../base/globals.h"
// [Api-Begin]
#include "../apibegin.h"
namespace
asmjit
{
//! \addtogroup asmjit_base_util
//! \{
// ============================================================================
// [asmjit::CpuTicks]
// ============================================================================
//! CPU ticks utilities.
struct
CpuTicks
{
//! Get the current CPU ticks for benchmarking (1ms resolution).
static
ASMJIT_API
uint32_t
now
();
};
//! \}
}
// asmjit namespace
// [Api-End]
#include "../apiend.h"
// [Guard]
#endif // _ASMJIT_BASE_CPUTICKS_H
libraries/asmjit/base/error.cpp
0 → 100644
View file @
61d5cc0f
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Export]
#define ASMJIT_EXPORTS
// [Dependencies - AsmJit]
#include "../base/error.h"
#include "../base/intutil.h"
// [Api-Begin]
#include "../apibegin.h"
namespace
asmjit
{
// ============================================================================
// [asmjit::ErrorHandler - Construction / Destruction]
// ============================================================================
ErrorHandler
::
ErrorHandler
()
{}
ErrorHandler
::~
ErrorHandler
()
{}
// ============================================================================
// [asmjit::ErrorHandler - Interface]
// ============================================================================
ErrorHandler
*
ErrorHandler
::
addRef
()
const
{
return
const_cast
<
ErrorHandler
*>
(
this
);
}
void
ErrorHandler
::
release
()
{}
// ============================================================================
// [asmjit::ErrorUtil - AsString]
// ============================================================================
#if !defined(ASMJIT_DISABLE_NAMES)
static
const
char
errorMessages
[]
=
{
"Ok
\0
"
"No heap memory
\0
"
"No virtual memory
\0
"
"Invalid argument
\0
"
"Invalid state
\0
"
"No code generated
\0
"
"Code too large
\0
"
"Label already bound
\0
"
"Unknown instruction
\0
"
"Illegal instruction
\0
"
"Illegal addressing
\0
"
"Illegal displacement
\0
"
"Overlapped arguments
\0
"
"Unknown error
\0
"
};
static
const
char
*
findPackedString
(
const
char
*
p
,
uint32_t
id
,
uint32_t
maxId
)
{
uint32_t
i
=
0
;
if
(
id
>
maxId
)
id
=
maxId
;
while
(
i
<
id
)
{
while
(
p
[
0
])
p
++
;
p
++
;
i
++
;
}
return
p
;
}
const
char
*
ErrorUtil
::
asString
(
Error
e
)
{
return
findPackedString
(
errorMessages
,
e
,
kErrorCount
);
}
#endif // ASMJIT_DISABLE_NAMES
}
// asmjit namespace
// [Api-End]
#include "../apiend.h"
libraries/asmjit/base/error.h
0 → 100644
View file @
61d5cc0f
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Guard]
#ifndef _ASMJIT_BASE_ERROR_H
#define _ASMJIT_BASE_ERROR_H
// [Dependencies - AsmJit]
#include "../base/globals.h"
// [Api-Begin]
#include "../apibegin.h"
namespace
asmjit
{
//! \addtogroup asmjit_base_general
//! \{
// ============================================================================
// [asmjit::ErrorCode]
// ============================================================================
//! AsmJit error codes.
ASMJIT_ENUM
(
ErrorCode
)
{
//! No error (success).
//!
//! This is default state and state you want.
kErrorOk
=
0
,
//! Heap memory allocation failed.
kErrorNoHeapMemory
=
1
,
//! Virtual memory allocation failed.
kErrorNoVirtualMemory
=
2
,
//! Invalid argument.
kErrorInvalidArgument
=
3
,
//! Invalid state.
kErrorInvalidState
=
4
,
//! No code generated.
//!
//! Returned by runtime if the code-generator contains no code.
kErrorNoCodeGenerated
=
5
,
//! Code generated is too large to fit in memory reserved.
//!
//! Returned by `StaticRuntime` in case that the code generated is too large
//! to fit in the memory already reserved for it.
kErrorCodeTooLarge
=
6
,
//! Label is already bound.
kErrorLabelAlreadyBound
=
7
,
//! Unknown instruction (an instruction ID is out of bounds or instruction
//! name is invalid).
kErrorUnknownInst
=
8
,
//! Illegal instruction.
//!
//! 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 `kErrorIllegalInst` error.
//!
//! ~~~
//! // Invalid address size.
//! a.mov(dword_ptr(eax), al);
//!
//! // 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 assertion is raised instead of returning an error.
kErrorIllegalInst
=
9
,
//! Illegal (unencodable) addressing used.
kErrorIllegalAddresing
=
10
,
//! Illegal (unencodable) displacement used.
//!
//! X86/X64
//! -------
//!
//! Short form of jump instruction has been used, but the displacement is out
//! of bounds.
kErrorIllegalDisplacement
=
11
,
//! A variable has been assigned more than once to a function argument (Compiler).
kErrorOverlappedArgs
=
12
,
//! Count of AsmJit error codes.
kErrorCount
=
13
};
// ============================================================================
// [asmjit::Error]
// ============================================================================
//! AsmJit error type (unsigned integer).
typedef
uint32_t
Error
;
// ============================================================================
// [asmjit::ErrorHandler]
// ============================================================================
//! Error handler.
//!
//! Error handler can be used to override the default behavior of `CodeGen`
//! error handling and propagation. See `handleError` on how to override it.
//!
//! Please note that `addRef` and `release` functions are used, but there is
//! no reference counting implemented by default, reimplement to change the
//! default behavior.
struct
ASMJIT_VCLASS
ErrorHandler
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! Create a new `ErrorHandler` instance.
ASMJIT_API
ErrorHandler
();
//! Destroy the `ErrorHandler` instance.
ASMJIT_API
virtual
~
ErrorHandler
();
// --------------------------------------------------------------------------
// [Interface]
// --------------------------------------------------------------------------
//! Reference this error handler.
//!
//! \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
//! case `addRef()` and `release()` functions should be overridden.
ASMJIT_API
virtual
ErrorHandler
*
addRef
()
const
;
//! Release this error handler.
//!
//! \note This member function is provided for convenience. See `addRef()`
//! for more detailed information related to reference counting.
ASMJIT_API
virtual
void
release
();
//! Error handler (pure).
//!
//! Error handler is called when an error happened. An error can happen in
//! many places, but error handler is mostly used by `Assembler` and
//! `Compiler` classes to report anything that may cause incorrect code
//! generation. There are multiple ways how the error handler can be used
//! and each has it's pros/cons.
//!
//! AsmJit library doesn't use exceptions and can be compiled with or without
//! exception handling support. Even if the AsmJit library is compiled without
//! exceptions it is exception-safe and handleError() can report an incoming
//! error by throwing an exception of any type. It's guaranteed that the
//! exception won't be catched by AsmJit and will be propagated to the code
//! calling AsmJit `Assembler` or `Compiler` methods. Alternative to
//! throwing an exception is using `setjmp()` and `longjmp()` pair available
//! in the standard C library.
//!
//! If the exception or setjmp() / longjmp() mechanism is used, the state of
//! the `BaseAssember` or `Compiler` is unchanged and if it's possible the
//! execution (instruction serialization) can continue. However if the error
//! happened during any phase that translates or modifies the stored code
//! (for example relocation done by `Assembler` or analysis/translation
//! done by `Compiler`) the execution can't continue and the error will
//! be also stored in `Assembler` or `Compiler`.
//!
//! Finally, if no exceptions nor setjmp() / longjmp() mechanisms were used,
//! you can still implement a compatible handling by returning from your
//! error handler. Returning `true` means that error was reported and AsmJit
//! should continue execution, but `false` sets the rror immediately to the
//! `Assembler` or `Compiler` and execution shouldn't continue (this
//! is the default behavior in case no error handler is used).
virtual
bool
handleError
(
Error
code
,
const
char
*
message
)
=
0
;
};
// ============================================================================
// [asmjit::ErrorUtil]
// ============================================================================
//! Error utilities.
struct
ErrorUtil
{
#if !defined(ASMJIT_DISABLE_NAMES)
//! Get a printable version of AsmJit `Error` code.
static
ASMJIT_API
const
char
*
asString
(
Error
code
);
#endif // ASMJIT_DISABLE_NAMES
};
//! \}
// ============================================================================
// [ASMJIT_PROPAGATE_ERROR]
// ============================================================================
//! \internal
//!
//! Used by AsmJit to return the `_Exp_` result if it's an error.
#define ASMJIT_PROPAGATE_ERROR(_Exp_) \
do { \
::asmjit::Error errval_ = (_Exp_); \
if (errval_ != ::asmjit::kErrorOk) \
return errval_; \
} while (0)
}
// asmjit namespace
// [Api-End]
#include "../apiend.h"
// [Guard]
#endif // _ASMJIT_BASE_ERROR_H
libraries/asmjit/base/globals.cpp
0 → 100644
View file @
61d5cc0f
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Export]
#define ASMJIT_EXPORTS
// [Dependencies - AsmJit]
#include "../base/globals.h"
// [Api-Begin]
#include "../apibegin.h"
namespace
asmjit
{
// ============================================================================
// [asmjit::Assert]
// ============================================================================
void
assertionFailed
(
const
char
*
exp
,
const
char
*
file
,
int
line
)
{
::
fprintf
(
stderr
,
"Assertion failed: %s
\n
, file %s, line %d
\n
"
,
exp
,
file
,
line
);
::
abort
();
}
}
// asmjit namespace
// [Api-End]
#include "../apiend.h"
libraries/asmjit/base/globals.h
0 → 100644
View file @
61d5cc0f
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Guard]
#ifndef _ASMJIT_BASE_GLOBALS_H
#define _ASMJIT_BASE_GLOBALS_H
// [Dependencies - AsmJit]
#include "../build.h"
// [Api-Begin]
#include "../apibegin.h"
namespace
asmjit
{
//! \addtogroup asmjit_base_general
//! \{
// ============================================================================
// [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::GlobalDefs]
// ============================================================================
//! 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
);
//! Invalid base address.
static
const
Ptr
kNoBaseAddress
=
static_cast
<
Ptr
>
(
static_cast
<
SignedPtr
>
(
-
1
));
//! Global constants.
ASMJIT_ENUM
(
GlobalDefs
)
{
//! Invalid value or operand id.
kInvalidValue
=
0xFFFFFFFF
,
//! Invalid register index.
kInvalidReg
=
0xFF
,
//! Invalid variable type.
kInvalidVar
=
0xFF
,
//! 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
};
// ============================================================================
// [asmjit::ArchId]
// ============================================================================
//! CPU architecture identifier.
ASMJIT_ENUM
(
ArchId
)
{
//! No/Unknown architecture.
kArchNone
=
0
,
//! X86 architecture.
kArchX86
=
1
,
//! X64 architecture, also called AMD64.
kArchX64
=
2
,
//! Arm architecture.
kArchArm
=
4
,
#if defined(ASMJIT_ARCH_X86)
kArchHost
=
kArchX86
,
#endif // ASMJIT_ARCH_X86
#if defined(ASMJIT_ARCH_X64)
kArchHost
=
kArchX64
,
#endif // ASMJIT_ARCH_X64
#if defined(ASMJIT_ARCH_ARM)
kArchHost
=
kArchArm
,
#endif // ASMJIT_ARCH_ARM
//! Whether the host is 64-bit.
kArchHost64Bit
=
sizeof
(
intptr_t
)
>=
8
};
//! \}
// ============================================================================
// [asmjit::Init / NoInit]
// ============================================================================
#if !defined(ASMJIT_DOCGEN)
struct
_Init
{};
static
const
_Init
Init
=
{};
struct
_NoInit
{};
static
const
_NoInit
NoInit
=
{};
#endif // !ASMJIT_DOCGEN
// ============================================================================
// [asmjit::Assert]
// ============================================================================
//! \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.
//!
//! If you have problems with assertions put a breakpoint at assertionFailed()
//! 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)
#define ASMJIT_ASSERT(_Exp_) \
do { \
if (!(_Exp_)) ::asmjit::assertionFailed(#_Exp_, __FILE__, __LINE__); \
} while (0)
#else
#define ASMJIT_ASSERT(_Exp_) ASMJIT_NOP()
#endif // DEBUG
//! \}
}
// asmjit namespace
// ============================================================================
// [asmjit_cast<>]
// ============================================================================
//! \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.
//!
//! If you are using single compiler and `reinterpret_cast<>` works for you,
//! there is no reason to use `asmjit_cast<>`. If you are writing
//! cross-platform software with various compiler support, consider using
//! `asmjit_cast<>` instead of `reinterpret_cast<>`.
template
<
typename
T
,
typename
Z
>
static
ASMJIT_INLINE
T
asmjit_cast
(
Z
*
p
)
{
return
(
T
)
p
;
}
//! \}
// [Api-End]
#include "../apiend.h"
// [Guard]
#endif // _ASMJIT_BASE_GLOBALS_H
libraries/asmjit/base/intutil.cpp
0 → 100644
View file @
61d5cc0f
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Export]
#define ASMJIT_EXPORTS
// [Dependencies - AsmJit]
#include "../base/intutil.h"
// [Api-Begin]
#include "../apibegin.h"
namespace
asmjit
{
#if defined(ASMJIT_TEST)
UNIT
(
base_intutil
)
{
uint32_t
i
;
INFO
(
"IntTraits<>."
);
EXPECT
(
IntTraits
<
signed
char
>::
kIsSigned
,
"IntTraits<signed char> should report signed."
);
EXPECT
(
IntTraits
<
unsigned
char
>::
kIsUnsigned
,
"IntTraits<unsigned char> should report unsigned."
);
EXPECT
(
IntTraits
<
signed
short
>::
kIsSigned
,
"IntTraits<signed short> should report signed."
);
EXPECT
(
IntTraits
<
unsigned
short
>::
kIsUnsigned
,
"IntTraits<unsigned short> should report unsigned."
);
EXPECT
(
IntTraits
<
int
>::
kIsSigned
,
"IntTraits<int> should report signed."
);
EXPECT
(
IntTraits
<
unsigned
int
>::
kIsUnsigned
,
"IntTraits<unsigned int> should report unsigned."
);
EXPECT
(
IntTraits
<
long
>::
kIsSigned
,
"IntTraits<long> should report signed."
);
EXPECT
(
IntTraits
<
unsigned
long
>::
kIsUnsigned
,
"IntTraits<unsigned long> should report unsigned."
);
EXPECT
(
IntTraits
<
intptr_t
>::
kIsSigned
,
"IntTraits<intptr_t> should report signed."
);
EXPECT
(
IntTraits
<
uintptr_t
>::
kIsUnsigned
,
"IntTraits<uintptr_t> should report unsigned."
);
EXPECT
(
IntTraits
<
intptr_t
>::
kIsIntPtr
,
"IntTraits<intptr_t> should report intptr_t type."
);
EXPECT
(
IntTraits
<
uintptr_t
>::
kIsIntPtr
,
"IntTraits<uintptr_t> should report intptr_t type."
);
INFO
(
"IntUtil::iMin()/iMax()."
);
EXPECT
(
IntUtil
::
iMin
<
int
>
(
0
,
-
1
)
==
-
1
,
"IntUtil::iMin<int> should return a minimum value."
);
EXPECT
(
IntUtil
::
iMin
<
int
>
(
-
1
,
-
2
)
==
-
2
,
"IntUtil::iMin<int> should return a minimum value."
);
EXPECT
(
IntUtil
::
iMin
<
int
>
(
1
,
2
)
==
1
,
"IntUtil::iMin<int> should return a minimum value."
);
EXPECT
(
IntUtil
::
iMax
<
int
>
(
0
,
-
1
)
==
0
,
"IntUtil::iMax<int> should return a maximum value."
);
EXPECT
(
IntUtil
::
iMax
<
int
>
(
-
1
,
-
2
)
==
-
1
,
"IntUtil::iMax<int> should return a maximum value."
);
EXPECT
(
IntUtil
::
iMax
<
int
>
(
1
,
2
)
==
2
,
"IntUtil::iMax<int> should return a maximum value."
);
INFO
(
"IntUtil::inInterval()."
);
EXPECT
(
IntUtil
::
inInterval
<
int
>
(
11
,
10
,
20
)
==
true
,
"IntUtil::inInterval<int> should return true if inside."
);
EXPECT
(
IntUtil
::
inInterval
<
int
>
(
101
,
10
,
20
)
==
false
,
"IntUtil::inInterval<int> should return false if outside."
);
INFO
(
"IntUtil::isInt8()."
);
EXPECT
(
IntUtil
::
isInt8
(
-
128
)
==
true
,
"IntUtil::isInt8<> should return true if inside."
);
EXPECT
(
IntUtil
::
isInt8
(
127
)
==
true
,
"IntUtil::isInt8<> should return true if inside."
);
EXPECT
(
IntUtil
::
isInt8
(
-
129
)
==
false
,
"IntUtil::isInt8<> should return false if outside."
);
EXPECT
(
IntUtil
::
isInt8
(
128
)
==
false
,
"IntUtil::isInt8<> should return false if outside."
);
INFO
(
"IntUtil::isUInt8()."
);
EXPECT
(
IntUtil
::
isUInt8
(
255
)
==
true
,
"IntUtil::isUInt8<> should return true if inside."
);
EXPECT
(
IntUtil
::
isUInt8
(
256
)
==
false
,
"IntUtil::isUInt8<> should return false if outside."
);
EXPECT
(
IntUtil
::
isUInt8
(
-
1
)
==
false
,
"IntUtil::isUInt8<> should return false if negative."
);
INFO
(
"IntUtil::isInt16()."
);
EXPECT
(
IntUtil
::
isInt16
(
-
32768
)
==
true
,
"IntUtil::isInt16<> should return true if inside."
);
EXPECT
(
IntUtil
::
isInt16
(
32767
)
==
true
,
"IntUtil::isInt16<> should return true if inside."
);
EXPECT
(
IntUtil
::
isInt16
(
-
32769
)
==
false
,
"IntUtil::isInt16<> should return false if outside."
);
EXPECT
(
IntUtil
::
isInt16
(
32768
)
==
false
,
"IntUtil::isInt16<> should return false if outside."
);
INFO
(
"IntUtil::isUInt16()."
);
EXPECT
(
IntUtil
::
isUInt16
(
65535
)
==
true
,
"IntUtil::isUInt16<> should return true if inside."
);
EXPECT
(
IntUtil
::
isUInt16
(
65536
)
==
false
,
"IntUtil::isUInt16<> should return false if outside."
);
EXPECT
(
IntUtil
::
isUInt16
(
-
1
)
==
false
,
"IntUtil::isUInt16<> should return false if negative."
);
INFO
(
"IntUtil::isInt32()."
);
EXPECT
(
IntUtil
::
isInt32
(
2147483647
)
==
true
,
"IntUtil::isInt32<int> should return true if inside."
);
EXPECT
(
IntUtil
::
isInt32
(
-
2147483647
-
1
)
==
true
,
"IntUtil::isInt32<int> should return true if inside."
);
EXPECT
(
IntUtil
::
isInt32
(
ASMJIT_UINT64_C
(
2147483648
))
==
false
,
"IntUtil::isInt32<int> should return false if outside."
);
EXPECT
(
IntUtil
::
isInt32
(
ASMJIT_UINT64_C
(
0xFFFFFFFF
))
==
false
,
"IntUtil::isInt32<int> should return false if outside."
);
EXPECT
(
IntUtil
::
isInt32
(
ASMJIT_UINT64_C
(
0xFFFFFFFF
)
+
1
)
==
false
,
"IntUtil::isInt32<int> should return false if outside."
);
INFO
(
"IntUtil::isUInt32()."
);
EXPECT
(
IntUtil
::
isUInt32
(
ASMJIT_UINT64_C
(
0xFFFFFFFF
))
==
true
,
"IntUtil::isUInt32<int> should return true if inside."
);
EXPECT
(
IntUtil
::
isUInt32
(
ASMJIT_UINT64_C
(
0xFFFFFFFF
)
+
1
)
==
false
,
"IntUtil::isUInt32<int> should return false if outside."
);
EXPECT
(
IntUtil
::
isUInt32
(
-
1
)
==
false
,
"IntUtil::isUInt32<int> should return false if negative."
);
INFO
(
"IntUtil::isPower2()."
);
for
(
i
=
0
;
i
<
64
;
i
++
)
{
EXPECT
(
IntUtil
::
isPowerOf2
(
static_cast
<
uint64_t
>
(
1
)
<<
i
)
==
true
,
"IntUtil::isPower2() didn't report power of 2."
);
EXPECT
(
IntUtil
::
isPowerOf2
((
static_cast
<
uint64_t
>
(
1
)
<<
i
)
^
0x001101
)
==
false
,
"IntUtil::isPower2() didn't report not power of 2."
);
}
INFO
(
"IntUtil::mask()."
);
for
(
i
=
0
;
i
<
32
;
i
++
)
{
EXPECT
(
IntUtil
::
mask
(
i
)
==
(
1
<<
i
),
"IntUtil::mask(%u) should return %X."
,
i
,
(
1
<<
i
));
}
INFO
(
"IntUtil::bits()."
);
for
(
i
=
0
;
i
<
32
;
i
++
)
{
uint32_t
expectedBits
=
0
;
for
(
uint32_t
b
=
0
;
b
<
i
;
b
++
)
expectedBits
|=
static_cast
<
uint32_t
>
(
1
)
<<
b
;
EXPECT
(
IntUtil
::
bits
(
i
)
==
expectedBits
,
"IntUtil::bits(%u) should return %X."
,
i
,
expectedBits
);
}
INFO
(
"IntUtil::hasBit()."
);
for
(
i
=
0
;
i
<
32
;
i
++
)
{
EXPECT
(
IntUtil
::
hasBit
((
1
<<
i
),
i
)
==
true
,
"IntUtil::hasBit(%X, %u) should return true."
,
(
1
<<
i
),
i
);
}
INFO
(
"IntUtil::bitCount()."
);
for
(
i
=
0
;
i
<
32
;
i
++
)
{
EXPECT
(
IntUtil
::
bitCount
((
1
<<
i
))
==
1
,
"IntUtil::bitCount(%X) should return true."
,
(
1
<<
i
));
}
EXPECT
(
IntUtil
::
bitCount
(
0x000000F0
)
==
4
,
""
);
EXPECT
(
IntUtil
::
bitCount
(
0x10101010
)
==
4
,
""
);
EXPECT
(
IntUtil
::
bitCount
(
0xFF000000
)
==
8
,
""
);
EXPECT
(
IntUtil
::
bitCount
(
0xFFFFFFF7
)
==
31
,
""
);
EXPECT
(
IntUtil
::
bitCount
(
0x7FFFFFFF
)
==
31
,
""
);
INFO
(
"IntUtil::findFirstBit()."
);
for
(
i
=
0
;
i
<
32
;
i
++
)
{
EXPECT
(
IntUtil
::
findFirstBit
((
1
<<
i
))
==
i
,
"IntUtil::findFirstBit(%X) should return %u."
,
(
1
<<
i
),
i
);
}
INFO
(
"IntUtil::isAligned()."
);
EXPECT
(
IntUtil
::
isAligned
<
size_t
>
(
0xFFFF
,
4
)
==
false
,
""
);
EXPECT
(
IntUtil
::
isAligned
<
size_t
>
(
0xFFF4
,
4
)
==
true
,
""
);
EXPECT
(
IntUtil
::
isAligned
<
size_t
>
(
0xFFF8
,
8
)
==
true
,
""
);
EXPECT
(
IntUtil
::
isAligned
<
size_t
>
(
0xFFF0
,
16
)
==
true
,
""
);
INFO
(
"IntUtil::alignTo()."
);
EXPECT
(
IntUtil
::
alignTo
<
size_t
>
(
0xFFFF
,
4
)
==
0x10000
,
""
);
EXPECT
(
IntUtil
::
alignTo
<
size_t
>
(
0xFFF4
,
4
)
==
0x0FFF4
,
""
);
EXPECT
(
IntUtil
::
alignTo
<
size_t
>
(
0xFFF8
,
8
)
==
0x0FFF8
,
""
);
EXPECT
(
IntUtil
::
alignTo
<
size_t
>
(
0xFFF0
,
16
)
==
0x0FFF0
,
""
);
EXPECT
(
IntUtil
::
alignTo
<
size_t
>
(
0xFFF0
,
32
)
==
0x10000
,
""
);
INFO
(
"IntUtil::alignToPowerOf2()."
);
EXPECT
(
IntUtil
::
alignToPowerOf2
<
size_t
>
(
0xFFFF
)
==
0x10000
,
""
);
EXPECT
(
IntUtil
::
alignToPowerOf2
<
size_t
>
(
0xF123
)
==
0x10000
,
""
);
EXPECT
(
IntUtil
::
alignToPowerOf2
<
size_t
>
(
0x0F00
)
==
0x01000
,
""
);
EXPECT
(
IntUtil
::
alignToPowerOf2
<
size_t
>
(
0x0100
)
==
0x00100
,
""
);
EXPECT
(
IntUtil
::
alignToPowerOf2
<
size_t
>
(
0x1001
)
==
0x02000
,
""
);
INFO
(
"IntUtil::deltaTo()."
);
EXPECT
(
IntUtil
::
deltaTo
<
size_t
>
(
0xFFFF
,
4
)
==
1
,
""
);
EXPECT
(
IntUtil
::
deltaTo
<
size_t
>
(
0xFFF4
,
4
)
==
0
,
""
);
EXPECT
(
IntUtil
::
deltaTo
<
size_t
>
(
0xFFF8
,
8
)
==
0
,
""
);
EXPECT
(
IntUtil
::
deltaTo
<
size_t
>
(
0xFFF0
,
16
)
==
0
,
""
);
EXPECT
(
IntUtil
::
deltaTo
<
size_t
>
(
0xFFF0
,
32
)
==
16
,
""
);
}
#endif // ASMJIT_TEST
}
// asmjit namespace
// [Api-End]
#include "../apiend.h"
libraries/asmjit/base/intutil.h
0 → 100644
View file @
61d5cc0f
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Guard]
#ifndef _ASMJIT_BASE_INTUTIL_H
#define _ASMJIT_BASE_INTUTIL_H
// [Dependencies - AsmJit]
#include "../base/globals.h"
#if defined(_MSC_VER) && _MSC_VER >= 1400
# include <intrin.h>
# pragma intrinsic(_BitScanForward)
#endif // ASMJIT_OS_WINDOWS
// [Api-Begin]
#include "../apibegin.h"
namespace
asmjit
{
//! \addtogroup asmjit_base_util
//! \{
// ============================================================================
// [asmjit::IntTraits]
// ============================================================================
//! \internal
template
<
typename
T
>
struct
IntTraits
{
enum
{
kIsSigned
=
static_cast
<
T
>
(
~
static_cast
<
T
>
(
0
))
<
static_cast
<
T
>
(
0
),
kIsUnsigned
=
!
kIsSigned
,
kIs8Bit
=
sizeof
(
T
)
==
1
,
kIs16Bit
=
sizeof
(
T
)
==
2
,
kIs32Bit
=
sizeof
(
T
)
==
4
,
kIs64Bit
=
sizeof
(
T
)
==
8
,
kIsIntPtr
=
sizeof
(
T
)
==
sizeof
(
intptr_t
)
};
};
// \internal
template
<
size_t
Size
,
int
IsSigned
>
struct
AsInt_
{
typedef
int64_t
Int
;
};
template
<
>
struct
AsInt_
<
1
,
0
>
{
typedef
int
Int
;
};
template
<
>
struct
AsInt_
<
1
,
1
>
{
typedef
int
Int
;
};
template
<
>
struct
AsInt_
<
2
,
0
>
{
typedef
int
Int
;
};
template
<
>
struct
AsInt_
<
2
,
1
>
{
typedef
int
Int
;
};
template
<
>
struct
AsInt_
<
4
,
1
>
{
typedef
int
Int
;
};
// \internal
//
// Map an integer `T` to an `int` or `int64_t`, depending on the type. Used
// internally by AsmJit to dispatch an argument of arbitrary integer type into
// a function that accepts either `int` or `int64_t`.
template
<
typename
T
>
struct
AsInt
{
typedef
typename
AsInt_
<
sizeof
(
T
),
IntTraits
<
T
>::
kIsSigned
>::
Int
Int
;
};
template
<
typename
T
>
ASMJIT_INLINE
typename
AsInt
<
T
>::
Int
asInt
(
T
value
)
{
return
static_cast
<
typename
AsInt
<
T
>::
Int
>
(
value
);
}
// ============================================================================
// [asmjit::IntUtil]
// ============================================================================
//! Integer utilities.
struct
IntUtil
{
// --------------------------------------------------------------------------
// [Float <-> Int]
// --------------------------------------------------------------------------
//! \internal
union
Float
{
int32_t
i
;
float
f
;
};
//! \internal
union
Double
{
int64_t
i
;
double
d
;
};
//! Bit-cast `float` to 32-bit integer.
static
ASMJIT_INLINE
int32_t
floatAsInt
(
float
f
)
{
Float
m
;
m
.
f
=
f
;
return
m
.
i
;
}
//! Bit-cast 32-bit integer to `float`.
static
ASMJIT_INLINE
float
intAsFloat
(
int32_t
i
)
{
Float
m
;
m
.
i
=
i
;
return
m
.
f
;
}
//! Bit-cast `double` to 64-bit integer.
static
ASMJIT_INLINE
int64_t
doubleAsInt
(
double
d
)
{
Double
m
;
m
.
d
=
d
;
return
m
.
i
;
}
//! Bit-cast 64-bit integer to `double`.
static
ASMJIT_INLINE
double
intAsDouble
(
int64_t
i
)
{
Double
m
;
m
.
i
=
i
;
return
m
.
d
;
}
// --------------------------------------------------------------------------
// [AsmJit - Pack / Unpack]
// --------------------------------------------------------------------------
//! Pack two 8-bit integer and one 16-bit integer into a 32-bit integer as it
//! is an array of `{u0,u1,w2}`.
static
ASMJIT_INLINE
uint32_t
pack32_2x8_1x16
(
uint32_t
u0
,
uint32_t
u1
,
uint32_t
w2
)
{
#if defined(ASMJIT_ARCH_LE)
return
u0
+
(
u1
<<
8
)
+
(
w2
<<
16
);
#else
return
(
u0
<<
24
)
+
(
u1
<<
16
)
+
(
w2
);
#endif
}
//! Pack four 8-bit integer into a 32-bit integer as it is an array of `{u0,u1,u2,u3}`.
static
ASMJIT_INLINE
uint32_t
pack32_4x8
(
uint32_t
u0
,
uint32_t
u1
,
uint32_t
u2
,
uint32_t
u3
)
{
#if defined(ASMJIT_ARCH_LE)
return
u0
+
(
u1
<<
8
)
+
(
u2
<<
16
)
+
(
u3
<<
24
);
#else
return
(
u0
<<
24
)
+
(
u1
<<
16
)
+
(
u2
<<
8
)
+
u3
;
#endif
}
//! Pack two 32-bit integer into a 64-bit integer as it is an array of `{u0,u1}`.
static
ASMJIT_INLINE
uint64_t
pack64_2x32
(
uint32_t
u0
,
uint32_t
u1
)
{
#if defined(ASMJIT_ARCH_LE)
return
(
static_cast
<
uint64_t
>
(
u1
)
<<
32
)
+
u0
;
#else
return
(
static_cast
<
uint64_t
>
(
u0
)
<<
32
)
+
u1
;
#endif
}
// --------------------------------------------------------------------------
// [AsmJit - Min/Max]
// --------------------------------------------------------------------------
// NOTE: Because some environments declare min() and max() as macros, it has
// been decided to use different name so we never collide with them.
//! Get minimum value of `a` and `b`.
template
<
typename
T
>
static
ASMJIT_INLINE
T
iMin
(
const
T
&
a
,
const
T
&
b
)
{
return
a
<
b
?
a
:
b
;
}
//! Get maximum value of `a` and `b`.
template
<
typename
T
>
static
ASMJIT_INLINE
T
iMax
(
const
T
&
a
,
const
T
&
b
)
{
return
a
>
b
?
a
:
b
;
}
// --------------------------------------------------------------------------
// [AsmJit - MaxUInt]
// --------------------------------------------------------------------------
//! Get maximum unsigned value of `T`.
template
<
typename
T
>
static
ASMJIT_INLINE
T
maxUInt
()
{
return
~
T
(
0
);
}
// --------------------------------------------------------------------------
// [AsmJit - InInterval]
// --------------------------------------------------------------------------
//! Get whether `x` is greater or equal than `start` and less or equal than `end`.
template
<
typename
T
>
static
ASMJIT_INLINE
bool
inInterval
(
const
T
&
x
,
const
T
&
start
,
const
T
&
end
)
{
return
x
>=
start
&&
x
<=
end
;
}
// --------------------------------------------------------------------------
// [AsmJit - IsInt/IsUInt]
// --------------------------------------------------------------------------
//! 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
)
return
sizeof
(
T
)
<=
sizeof
(
int8_t
)
?
true
:
x
>=
T
(
-
128
)
&&
x
<=
T
(
127
);
else
return
x
<=
T
(
127
);
}
//! 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
)
return
x
>=
T
(
0
)
&&
(
sizeof
(
T
)
<=
sizeof
(
uint8_t
)
?
true
:
x
<=
T
(
255
));
else
return
sizeof
(
T
)
<=
sizeof
(
uint8_t
)
?
true
:
x
<=
T
(
255
);
}
//! 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
)
return
sizeof
(
T
)
<=
sizeof
(
int16_t
)
?
true
:
x
>=
T
(
-
32768
)
&&
x
<=
T
(
32767
);
else
return
x
>=
T
(
0
)
&&
(
sizeof
(
T
)
<=
sizeof
(
int16_t
)
?
true
:
x
<=
T
(
32767
));
}
//! 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
)
return
x
>=
T
(
0
)
&&
(
sizeof
(
T
)
<=
sizeof
(
uint16_t
)
?
true
:
x
<=
T
(
65535
));
else
return
sizeof
(
T
)
<=
sizeof
(
uint16_t
)
?
true
:
x
<=
T
(
65535
);
}
//! 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
)
return
sizeof
(
T
)
<=
sizeof
(
int32_t
)
?
true
:
x
>=
T
(
-
2147483647
)
-
1
&&
x
<=
T
(
2147483647
);
else
return
x
>=
T
(
0
)
&&
(
sizeof
(
T
)
<=
sizeof
(
int32_t
)
?
true
:
x
<=
T
(
2147483647
));
}
//! 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
)
return
x
>=
T
(
0
)
&&
(
sizeof
(
T
)
<=
sizeof
(
uint32_t
)
?
true
:
x
<=
T
(
4294967295U
));
else
return
sizeof
(
T
)
<=
sizeof
(
uint32_t
)
?
true
:
x
<=
T
(
4294967295U
);
}
// --------------------------------------------------------------------------
// [AsmJit - IsPowerOf2]
// --------------------------------------------------------------------------
//! Get whether the `n` value is a power of two (only one bit is set).
template
<
typename
T
>
static
ASMJIT_INLINE
bool
isPowerOf2
(
T
n
)
{
return
n
!=
0
&&
(
n
&
(
n
-
1
))
==
0
;
}
// --------------------------------------------------------------------------
// [AsmJit - Mask]
// --------------------------------------------------------------------------
//! Generate a bit-mask that has `x` bit set.
static
ASMJIT_INLINE
uint32_t
mask
(
uint32_t
x
)
{
ASMJIT_ASSERT
(
x
<
32
);
return
(
1U
<<
x
);
}
//! Generate a bit-mask that has `x0` and `x1` bits set.
static
ASMJIT_INLINE
uint32_t
mask
(
uint32_t
x0
,
uint32_t
x1
)
{
return
mask
(
x0
)
|
mask
(
x1
);
}
//! Generate a bit-mask that has `x0`, `x1` and `x2` bits set.
static
ASMJIT_INLINE
uint32_t
mask
(
uint32_t
x0
,
uint32_t
x1
,
uint32_t
x2
)
{
return
mask
(
x0
)
|
mask
(
x1
)
|
mask
(
x2
);
}
//! Generate a bit-mask that has `x0`, `x1`, `x2` and `x3` bits set.
static
ASMJIT_INLINE
uint32_t
mask
(
uint32_t
x0
,
uint32_t
x1
,
uint32_t
x2
,
uint32_t
x3
)
{
return
mask
(
x0
)
|
mask
(
x1
)
|
mask
(
x2
)
|
mask
(
x3
);
}
//! Generate a bit-mask that has `x0`, `x1`, `x2`, `x3` and `x4` bits set.
static
ASMJIT_INLINE
uint32_t
mask
(
uint32_t
x0
,
uint32_t
x1
,
uint32_t
x2
,
uint32_t
x3
,
uint32_t
x4
)
{
return
mask
(
x0
)
|
mask
(
x1
)
|
mask
(
x2
)
|
mask
(
x3
)
|
mask
(
x4
)
;
}
//! Generate a bit-mask that has `x0`, `x1`, `x2`, `x3`, `x4` and `x5` bits set.
static
ASMJIT_INLINE
uint32_t
mask
(
uint32_t
x0
,
uint32_t
x1
,
uint32_t
x2
,
uint32_t
x3
,
uint32_t
x4
,
uint32_t
x5
)
{
return
mask
(
x0
)
|
mask
(
x1
)
|
mask
(
x2
)
|
mask
(
x3
)
|
mask
(
x4
)
|
mask
(
x5
)
;
}
//! Generate a bit-mask that has `x0`, `x1`, `x2`, `x3`, `x4`, `x5` and `x6` bits set.
static
ASMJIT_INLINE
uint32_t
mask
(
uint32_t
x0
,
uint32_t
x1
,
uint32_t
x2
,
uint32_t
x3
,
uint32_t
x4
,
uint32_t
x5
,
uint32_t
x6
)
{
return
mask
(
x0
)
|
mask
(
x1
)
|
mask
(
x2
)
|
mask
(
x3
)
|
mask
(
x4
)
|
mask
(
x5
)
|
mask
(
x6
)
;
}
//! Generate a bit-mask that has `x0`, `x1`, `x2`, `x3`, `x4`, `x5`, `x6` and `x7` bits set.
static
ASMJIT_INLINE
uint32_t
mask
(
uint32_t
x0
,
uint32_t
x1
,
uint32_t
x2
,
uint32_t
x3
,
uint32_t
x4
,
uint32_t
x5
,
uint32_t
x6
,
uint32_t
x7
)
{
return
mask
(
x0
)
|
mask
(
x1
)
|
mask
(
x2
)
|
mask
(
x3
)
|
mask
(
x4
)
|
mask
(
x5
)
|
mask
(
x6
)
|
mask
(
x7
)
;
}
//! Generate a bit-mask that has `x0`, `x1`, `x2`, `x3`, `x4`, `x5`, `x6`, `x7` and `x8` bits set.
static
ASMJIT_INLINE
uint32_t
mask
(
uint32_t
x0
,
uint32_t
x1
,
uint32_t
x2
,
uint32_t
x3
,
uint32_t
x4
,
uint32_t
x5
,
uint32_t
x6
,
uint32_t
x7
,
uint32_t
x8
)
{
return
mask
(
x0
)
|
mask
(
x1
)
|
mask
(
x2
)
|
mask
(
x3
)
|
mask
(
x4
)
|
mask
(
x5
)
|
mask
(
x6
)
|
mask
(
x7
)
|
mask
(
x8
)
;
}
//! Generate a bit-mask that has `x0`, `x1`, `x2`, `x3`, `x4`, `x5`, `x6`, `x7`, `x8` and `x9` bits set.
static
ASMJIT_INLINE
uint32_t
mask
(
uint32_t
x0
,
uint32_t
x1
,
uint32_t
x2
,
uint32_t
x3
,
uint32_t
x4
,
uint32_t
x5
,
uint32_t
x6
,
uint32_t
x7
,
uint32_t
x8
,
uint32_t
x9
)
{
return
mask
(
x0
)
|
mask
(
x1
)
|
mask
(
x2
)
|
mask
(
x3
)
|
mask
(
x4
)
|
mask
(
x5
)
|
mask
(
x6
)
|
mask
(
x7
)
|
mask
(
x8
)
|
mask
(
x9
)
;
}
// --------------------------------------------------------------------------
// [AsmJit - Bits]
// --------------------------------------------------------------------------
//! Generate a bit-mask that has `x` most significant bits set.
static
ASMJIT_INLINE
uint32_t
bits
(
uint32_t
x
)
{
// Shifting more bits that the type has has undefined behavior. Everything
// we need is that application shouldn't crash because of that, but the
// content of register after shift is not defined. So in case that the
// requested shift is too large for the type we correct this undefined
// behavior by setting all bits to ones (this is why we generate an overflow
// mask).
uint32_t
overflow
=
static_cast
<
uint32_t
>
(
-
static_cast
<
int32_t
>
(
x
>=
sizeof
(
uint32_t
)
*
8
));
return
((
static_cast
<
uint32_t
>
(
1
)
<<
x
)
-
1U
)
|
overflow
;
}
// --------------------------------------------------------------------------
// [AsmJit - HasBit]
// --------------------------------------------------------------------------
//! Get whether `x` has bit `n` set.
static
ASMJIT_INLINE
bool
hasBit
(
uint32_t
x
,
uint32_t
n
)
{
return
static_cast
<
bool
>
((
x
>>
n
)
&
0x1
);
}
// --------------------------------------------------------------------------
// [AsmJit - BitCount]
// --------------------------------------------------------------------------
//! Get count of bits in `x`.
//!
//! Taken from http://graphics.stanford.edu/~seander/bithacks.html .
static
ASMJIT_INLINE
uint32_t
bitCount
(
uint32_t
x
)
{
x
=
x
-
((
x
>>
1
)
&
0x55555555U
);
x
=
(
x
&
0x33333333U
)
+
((
x
>>
2
)
&
0x33333333U
);
return
(((
x
+
(
x
>>
4
))
&
0x0F0F0F0FU
)
*
0x01010101U
)
>>
24
;
}
// --------------------------------------------------------------------------
// [AsmJit - FindFirstBit]
// --------------------------------------------------------------------------
//! \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
// has been improved to check for 2 bits per iteration.
uint32_t
i
=
1
;
while
(
mask
!=
0
)
{
uint32_t
two
=
mask
&
0x3
;
if
(
two
!=
0x0
)
return
i
-
(
two
&
0x1
);
i
+=
2
;
mask
>>=
2
;
}
return
0xFFFFFFFFU
;
}
//! Find a first bit in `mask`.
static
ASMJIT_INLINE
uint32_t
findFirstBit
(
uint32_t
mask
)
{
#if defined(_MSC_VER) && _MSC_VER >= 1400
DWORD
i
;
if
(
_BitScanForward
(
&
i
,
mask
))
{
ASMJIT_ASSERT
(
findFirstBitSlow
(
mask
)
==
i
);
return
static_cast
<
uint32_t
>
(
i
);
}
return
0xFFFFFFFFU
;
#else
return
findFirstBitSlow
(
mask
);
#endif
}
// --------------------------------------------------------------------------
// [AsmJit - Misc]
// --------------------------------------------------------------------------
static
ASMJIT_INLINE
uint32_t
keepNOnesFromRight
(
uint32_t
mask
,
uint32_t
nBits
)
{
uint32_t
m
=
0x1
;
do
{
nBits
-=
(
mask
&
m
)
==
0
;
m
<<=
1
;
if
(
nBits
==
0
)
{
m
-=
1
;
mask
&=
m
;
break
;
}
}
while
(
m
);
return
mask
;
}
static
ASMJIT_INLINE
uint32_t
indexNOnesFromRight
(
uint8_t
*
dst
,
uint32_t
mask
,
uint32_t
nBits
)
{
uint32_t
totalBits
=
nBits
;
uint8_t
i
=
0
;
uint32_t
m
=
0x1
;
do
{
if
(
mask
&
m
)
{
*
dst
++
=
i
;
if
(
--
nBits
==
0
)
break
;
}
m
<<=
1
;
i
++
;
}
while
(
m
);
return
totalBits
-
nBits
;
}
// --------------------------------------------------------------------------
// [AsmJit - Alignment]
// --------------------------------------------------------------------------
template
<
typename
T
>
static
ASMJIT_INLINE
bool
isAligned
(
T
base
,
T
alignment
)
{
return
(
base
%
alignment
)
==
0
;
}
//! Align `base` to `alignment`.
template
<
typename
T
>
static
ASMJIT_INLINE
T
alignTo
(
T
base
,
T
alignment
)
{
return
(
base
+
(
alignment
-
1
))
&
~
(
alignment
-
1
);
}
template
<
typename
T
>
static
ASMJIT_INLINE
T
alignToPowerOf2
(
T
base
)
{
// Implementation is from "Hacker's Delight" by Henry S. Warren, Jr.
base
-=
1
;
#if defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable: 4293)
#endif // _MSC_VER
base
=
base
|
(
base
>>
1
);
base
=
base
|
(
base
>>
2
);
base
=
base
|
(
base
>>
4
);
// 8/16/32 constants are multiplied by the condition to prevent a compiler
// complaining about the 'shift count >= type width' (GCC).
if
(
sizeof
(
T
)
>=
2
)
base
=
base
|
(
base
>>
(
8
*
(
sizeof
(
T
)
>=
2
)));
// Base >> 8.
if
(
sizeof
(
T
)
>=
4
)
base
=
base
|
(
base
>>
(
16
*
(
sizeof
(
T
)
>=
4
)));
// Base >> 16.
if
(
sizeof
(
T
)
>=
8
)
base
=
base
|
(
base
>>
(
32
*
(
sizeof
(
T
)
>=
8
)));
// Base >> 32.
#if defined(_MSC_VER)
# pragma warning(pop)
#endif // _MSC_VER
return
base
+
1
;
}
//! Get delta required to align `base` to `alignment`.
template
<
typename
T
>
static
ASMJIT_INLINE
T
deltaTo
(
T
base
,
T
alignment
)
{
return
alignTo
(
base
,
alignment
)
-
base
;
}
};
// ============================================================================
// [asmjit::UInt64]
// ============================================================================
union
UInt64
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
ASMJIT_INLINE
UInt64
fromUInt64
(
uint64_t
val
)
{
UInt64
data
;
data
.
setUInt64
(
val
);
return
data
;
}
ASMJIT_INLINE
UInt64
fromUInt64
(
const
UInt64
&
val
)
{
UInt64
data
;
data
.
setUInt64
(
val
);
return
data
;
}
// --------------------------------------------------------------------------
// [Reset]
// --------------------------------------------------------------------------
ASMJIT_INLINE
void
reset
()
{
if
(
kArchHost64Bit
)
{
u64
=
0
;
}
else
{
u32
[
0
]
=
0
;
u32
[
1
]
=
0
;
}
}
// --------------------------------------------------------------------------
// [Accessors]
// --------------------------------------------------------------------------
ASMJIT_INLINE
uint64_t
getUInt64
()
const
{
return
u64
;
}
ASMJIT_INLINE
UInt64
&
setUInt64
(
uint64_t
val
)
{
u64
=
val
;
return
*
this
;
}
ASMJIT_INLINE
UInt64
&
setUInt64
(
const
UInt64
&
val
)
{
if
(
kArchHost64Bit
)
{
u64
=
val
.
u64
;
}
else
{
u32
[
0
]
=
val
.
u32
[
0
];
u32
[
1
]
=
val
.
u32
[
1
];
}
return
*
this
;
}
ASMJIT_INLINE
UInt64
&
setPacked_2x32
(
uint32_t
u0
,
uint32_t
u1
)
{
if
(
kArchHost64Bit
)
{
u64
=
IntUtil
::
pack64_2x32
(
u0
,
u1
);
}
else
{
u32
[
0
]
=
u0
;
u32
[
1
]
=
u1
;
}
return
*
this
;
}
// --------------------------------------------------------------------------
// [Add]
// --------------------------------------------------------------------------
ASMJIT_INLINE
UInt64
&
add
(
uint64_t
val
)
{
u64
+=
val
;
return
*
this
;
}
ASMJIT_INLINE
UInt64
&
add
(
const
UInt64
&
val
)
{
if
(
kArchHost64Bit
)
{
u64
+=
val
.
u64
;
}
else
{
u32
[
0
]
+=
val
.
u32
[
0
];
u32
[
1
]
+=
val
.
u32
[
1
];
}
return
*
this
;
}
// --------------------------------------------------------------------------
// [Sub]
// --------------------------------------------------------------------------
ASMJIT_INLINE
UInt64
&
sub
(
uint64_t
val
)
{
u64
-=
val
;
return
*
this
;
}
ASMJIT_INLINE
UInt64
&
sub
(
const
UInt64
&
val
)
{
if
(
kArchHost64Bit
)
{
u64
-=
val
.
u64
;
}
else
{
u32
[
0
]
-=
val
.
u32
[
0
];
u32
[
1
]
-=
val
.
u32
[
1
];
}
return
*
this
;
}
// --------------------------------------------------------------------------
// [And]
// --------------------------------------------------------------------------
ASMJIT_INLINE
UInt64
&
and_
(
uint64_t
val
)
{
u64
&=
val
;
return
*
this
;
}
ASMJIT_INLINE
UInt64
&
and_
(
const
UInt64
&
val
)
{
if
(
kArchHost64Bit
)
{
u64
&=
val
.
u64
;
}
else
{
u32
[
0
]
&=
val
.
u32
[
0
];
u32
[
1
]
&=
val
.
u32
[
1
];
}
return
*
this
;
}
// --------------------------------------------------------------------------
// [AndNot]
// --------------------------------------------------------------------------
ASMJIT_INLINE
UInt64
&
andNot
(
uint64_t
val
)
{
u64
&=
~
val
;
return
*
this
;
}
ASMJIT_INLINE
UInt64
&
andNot
(
const
UInt64
&
val
)
{
if
(
kArchHost64Bit
)
{
u64
&=
~
val
.
u64
;
}
else
{
u32
[
0
]
&=
~
val
.
u32
[
0
];
u32
[
1
]
&=
~
val
.
u32
[
1
];
}
return
*
this
;
}
// --------------------------------------------------------------------------
// [Or]
// --------------------------------------------------------------------------
ASMJIT_INLINE
UInt64
&
or_
(
uint64_t
val
)
{
u64
|=
val
;
return
*
this
;
}
ASMJIT_INLINE
UInt64
&
or_
(
const
UInt64
&
val
)
{
if
(
kArchHost64Bit
)
{
u64
|=
val
.
u64
;
}
else
{
u32
[
0
]
|=
val
.
u32
[
0
];
u32
[
1
]
|=
val
.
u32
[
1
];
}
return
*
this
;
}
// --------------------------------------------------------------------------
// [Xor]
// --------------------------------------------------------------------------
ASMJIT_INLINE
UInt64
&
xor_
(
uint64_t
val
)
{
u64
^=
val
;
return
*
this
;
}
ASMJIT_INLINE
UInt64
&
xor_
(
const
UInt64
&
val
)
{
if
(
kArchHost64Bit
)
{
u64
^=
val
.
u64
;
}
else
{
u32
[
0
]
^=
val
.
u32
[
0
];
u32
[
1
]
^=
val
.
u32
[
1
];
}
return
*
this
;
}
// --------------------------------------------------------------------------
// [Eq]
// --------------------------------------------------------------------------
ASMJIT_INLINE
bool
isZero
()
const
{
return
kArchHost64Bit
?
u64
==
0
:
(
u32
[
0
]
|
u32
[
1
])
==
0
;
}
ASMJIT_INLINE
bool
isNonZero
()
const
{
return
kArchHost64Bit
?
u64
!=
0
:
(
u32
[
0
]
|
u32
[
1
])
!=
0
;
}
ASMJIT_INLINE
bool
eq
(
uint64_t
val
)
const
{
return
u64
==
val
;
}
ASMJIT_INLINE
bool
eq
(
const
UInt64
&
val
)
const
{
return
kArchHost64Bit
?
u64
==
val
.
u64
:
(
u32
[
0
]
==
val
.
u32
[
0
])
&
(
u32
[
1
]
==
val
.
u32
[
1
]);
}
// --------------------------------------------------------------------------
// [Operator Overload]
// --------------------------------------------------------------------------
ASMJIT_INLINE
UInt64
&
operator
+=
(
uint64_t
val
)
{
return
add
(
val
);
}
ASMJIT_INLINE
UInt64
&
operator
+=
(
const
UInt64
&
val
)
{
return
add
(
val
);
}
ASMJIT_INLINE
UInt64
&
operator
-=
(
uint64_t
val
)
{
return
sub
(
val
);
}
ASMJIT_INLINE
UInt64
&
operator
-=
(
const
UInt64
&
val
)
{
return
sub
(
val
);
}
ASMJIT_INLINE
UInt64
&
operator
&=
(
uint64_t
val
)
{
return
and_
(
val
);
}
ASMJIT_INLINE
UInt64
&
operator
&=
(
const
UInt64
&
val
)
{
return
and_
(
val
);
}
ASMJIT_INLINE
UInt64
&
operator
|=
(
uint64_t
val
)
{
return
or_
(
val
);
}
ASMJIT_INLINE
UInt64
&
operator
|=
(
const
UInt64
&
val
)
{
return
or_
(
val
);
}
ASMJIT_INLINE
UInt64
&
operator
^=
(
uint64_t
val
)
{
return
xor_
(
val
);
}
ASMJIT_INLINE
UInt64
&
operator
^=
(
const
UInt64
&
val
)
{
return
xor_
(
val
);
}
ASMJIT_INLINE
bool
operator
==
(
uint64_t
val
)
const
{
return
eq
(
val
);
}
ASMJIT_INLINE
bool
operator
==
(
const
UInt64
&
val
)
const
{
return
eq
(
val
);
}
ASMJIT_INLINE
bool
operator
!=
(
uint64_t
val
)
const
{
return
!
eq
(
val
);
}
ASMJIT_INLINE
bool
operator
!=
(
const
UInt64
&
val
)
const
{
return
!
eq
(
val
);
}
ASMJIT_INLINE
bool
operator
<
(
uint64_t
val
)
const
{
return
u64
<
val
;
}
ASMJIT_INLINE
bool
operator
<
(
const
UInt64
&
val
)
const
{
return
u64
<
val
.
u64
;
}
ASMJIT_INLINE
bool
operator
<=
(
uint64_t
val
)
const
{
return
u64
<=
val
;
}
ASMJIT_INLINE
bool
operator
<=
(
const
UInt64
&
val
)
const
{
return
u64
<=
val
.
u64
;
}
ASMJIT_INLINE
bool
operator
>
(
uint64_t
val
)
const
{
return
u64
>
val
;
}
ASMJIT_INLINE
bool
operator
>
(
const
UInt64
&
val
)
const
{
return
u64
>
val
.
u64
;
}
ASMJIT_INLINE
bool
operator
>=
(
uint64_t
val
)
const
{
return
u64
>=
val
;
}
ASMJIT_INLINE
bool
operator
>=
(
const
UInt64
&
val
)
const
{
return
u64
>=
val
.
u64
;
}
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
uint64_t
u64
;
uint32_t
u32
[
2
];
uint16_t
u16
[
4
];
uint8_t
u8
[
8
];
struct
{
#if defined(ASMJIT_ARCH_LE)
uint32_t
lo
,
hi
;
#else
uint32_t
hi
,
lo
;
#endif // ASMJIT_ARCH_LE
};
};
//! \}
}
// asmjit namespace
// [Api-End]
#include "../apiend.h"
// [Guard]
#endif // _ASMJIT_BASE_INTUTIL_H
libraries/asmjit/base/lock.h
0 → 100644
View file @
61d5cc0f
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Guard]
#ifndef _ASMJIT_BASE_LOCK_H
#define _ASMJIT_BASE_LOCK_H
// [Dependencies - AsmJit]
#include "../build.h"
// [Dependencies - Posix]
#if defined(ASMJIT_OS_POSIX)
# include <pthread.h>
#endif // ASMJIT_OS_POSIX
// [Api-Begin]
#include "../apibegin.h"
namespace
asmjit
{
//! \addtogroup asmjit_base_util
//! \{
// ============================================================================
// [asmjit::Lock]
// ============================================================================
//! Lock - used in thread-safe code for locking.
struct
Lock
{
ASMJIT_NO_COPY
(
Lock
)
// --------------------------------------------------------------------------
// [Windows]
// --------------------------------------------------------------------------
#if defined(ASMJIT_OS_WINDOWS)
typedef
CRITICAL_SECTION
Handle
;
//! Create a new `Lock` instance.
ASMJIT_INLINE
Lock
()
{
InitializeCriticalSection
(
&
_handle
);
}
//! Destroy the `Lock` instance.
ASMJIT_INLINE
~
Lock
()
{
DeleteCriticalSection
(
&
_handle
);
}
//! Lock.
ASMJIT_INLINE
void
lock
()
{
EnterCriticalSection
(
&
_handle
);
}
//! Unlock.
ASMJIT_INLINE
void
unlock
()
{
LeaveCriticalSection
(
&
_handle
);
}
#endif // ASMJIT_OS_WINDOWS
// --------------------------------------------------------------------------
// [Posix]
// --------------------------------------------------------------------------
#if defined(ASMJIT_OS_POSIX)
typedef
pthread_mutex_t
Handle
;
//! Create a new `Lock` instance.
ASMJIT_INLINE
Lock
()
{
pthread_mutex_init
(
&
_handle
,
NULL
);
}
//! Destroy the `Lock` instance.
ASMJIT_INLINE
~
Lock
()
{
pthread_mutex_destroy
(
&
_handle
);
}
//! Lock.
ASMJIT_INLINE
void
lock
()
{
pthread_mutex_lock
(
&
_handle
);
}
//! Unlock.
ASMJIT_INLINE
void
unlock
()
{
pthread_mutex_unlock
(
&
_handle
);
}
#endif // ASMJIT_OS_POSIX
// --------------------------------------------------------------------------
// [Accessors]
// --------------------------------------------------------------------------
//! Get handle.
ASMJIT_INLINE
Handle
&
getHandle
()
{
return
_handle
;
}
//! \overload
ASMJIT_INLINE
const
Handle
&
getHandle
()
const
{
return
_handle
;
}
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
//! Handle.
Handle
_handle
;
};
// ============================================================================
// [asmjit::AutoLock]
// ============================================================================
//! Scoped lock.
struct
AutoLock
{
ASMJIT_NO_COPY
(
AutoLock
)
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! Autolock `target`, scoped.
ASMJIT_INLINE
AutoLock
(
Lock
&
target
)
:
_target
(
target
)
{
_target
.
lock
();
}
//! Autounlock `target`.
ASMJIT_INLINE
~
AutoLock
()
{
_target
.
unlock
();
}
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
//! Pointer to target (lock).
Lock
&
_target
;
};
//! \}
}
// asmjit namespace
// [Api-End]
#include "../apiend.h"
// [Guard]
#endif // _ASMJIT_BASE_LOCK_H
libraries/asmjit/base/logger.cpp
0 → 100644
View file @
61d5cc0f
// [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_DISABLE_LOGGER)
// [Dependencies - AsmJit]
#include "../base/intutil.h"
#include "../base/logger.h"
#include "../base/string.h"
// [Dependencies - C]
#include <stdarg.h>
// [Api-Begin]
#include "../apibegin.h"
namespace
asmjit
{
// ============================================================================
// [asmjit::Logger - Construction / Destruction]
// ============================================================================
Logger
::
Logger
()
{
_options
=
0
;
::
memset
(
_indentation
,
0
,
ASMJIT_ARRAY_SIZE
(
_indentation
));
}
Logger
::~
Logger
()
{}
// ============================================================================
// [asmjit::Logger - Logging]
// ============================================================================
void
Logger
::
logFormat
(
uint32_t
style
,
const
char
*
fmt
,
...)
{
char
buf
[
1024
];
size_t
len
;
va_list
ap
;
va_start
(
ap
,
fmt
);
len
=
vsnprintf
(
buf
,
sizeof
(
buf
),
fmt
,
ap
);
va_end
(
ap
);
if
(
len
>=
sizeof
(
buf
))
len
=
sizeof
(
buf
)
-
1
;
logString
(
style
,
buf
,
len
);
}
void
Logger
::
logBinary
(
uint32_t
style
,
const
void
*
data
,
size_t
size
)
{
static
const
char
prefix
[]
=
".data "
;
static
const
char
hex
[
16
]
=
{
'0'
,
'1'
,
'2'
,
'3'
,
'4'
,
'5'
,
'6'
,
'7'
,
'8'
,
'9'
,
'A'
,
'B'
,
'C'
,
'D'
,
'E'
,
'F'
};
const
uint8_t
*
s
=
static_cast
<
const
uint8_t
*>
(
data
);
size_t
i
=
size
;
char
buffer
[
128
];
::
memcpy
(
buffer
,
prefix
,
ASMJIT_ARRAY_SIZE
(
prefix
)
-
1
);
while
(
i
)
{
uint32_t
n
=
static_cast
<
uint32_t
>
(
IntUtil
::
iMin
<
size_t
>
(
i
,
16
));
char
*
p
=
buffer
+
ASMJIT_ARRAY_SIZE
(
prefix
)
-
1
;
i
-=
n
;
do
{
uint32_t
c
=
s
[
0
];
p
[
0
]
=
hex
[
c
>>
4
];
p
[
1
]
=
hex
[
c
&
15
];
p
+=
2
;
s
+=
1
;
}
while
(
--
n
);
*
p
++
=
'\n'
;
logString
(
style
,
buffer
,
(
size_t
)(
p
-
buffer
));
}
}
// ============================================================================
// [asmjit::Logger - LogBinary]
// ============================================================================
void
Logger
::
setOption
(
uint32_t
id
,
bool
value
)
{
if
(
id
>=
kLoggerOptionCount
)
return
;
uint32_t
mask
=
1
<<
id
;
if
(
value
)
_options
|=
mask
;
else
_options
&=
~
mask
;
}
// ============================================================================
// [asmjit::Logger - Indentation]
// ============================================================================
void
Logger
::
setIndentation
(
const
char
*
indentation
)
{
::
memset
(
_indentation
,
0
,
ASMJIT_ARRAY_SIZE
(
_indentation
));
if
(
!
indentation
)
return
;
size_t
length
=
StringUtil
::
nlen
(
indentation
,
ASMJIT_ARRAY_SIZE
(
_indentation
)
-
1
);
::
memcpy
(
_indentation
,
indentation
,
length
);
}
// ============================================================================
// [asmjit::FileLogger - Construction / Destruction]
// ============================================================================
FileLogger
::
FileLogger
(
FILE
*
stream
)
:
_stream
(
NULL
)
{
setStream
(
stream
);
}
FileLogger
::~
FileLogger
()
{}
// ============================================================================
// [asmjit::FileLogger - Logging]
// ============================================================================
void
FileLogger
::
logString
(
uint32_t
style
,
const
char
*
buf
,
size_t
len
)
{
if
(
!
_stream
)
return
;
if
(
len
==
kInvalidIndex
)
len
=
strlen
(
buf
);
fwrite
(
buf
,
1
,
len
,
_stream
);
}
// ============================================================================
// [asmjit::StringLogger - Construction / Destruction]
// ============================================================================
StringLogger
::
StringLogger
()
{}
StringLogger
::~
StringLogger
()
{}
// ============================================================================
// [asmjit::StringLogger - Logging]
// ============================================================================
void
StringLogger
::
logString
(
uint32_t
style
,
const
char
*
buf
,
size_t
len
)
{
_stringBuilder
.
appendString
(
buf
,
len
);
}
}
// asmjit namespace
// [Api-End]
#include "../apiend.h"
// [Guard]
#endif // !ASMJIT_DISABLE_LOGGER
libraries/asmjit/base/logger.h
0 → 100644
View file @
61d5cc0f
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Guard]
#ifndef _ASMJIT_BASE_LOGGER_H
#define _ASMJIT_BASE_LOGGER_H
#include "../build.h"
#if !defined(ASMJIT_DISABLE_LOGGER)
// [Dependencies - AsmJit]
#include "../base/string.h"
// [Dependencies - C]
#include <stdarg.h>
// [Api-Begin]
#include "../apibegin.h"
namespace
asmjit
{
//! \addtogroup asmjit_base_util
//! \{
// ============================================================================
// [asmjit::LoggerOption]
// ============================================================================
//! Logger options.
ASMJIT_ENUM
(
LoggerOption
)
{
//! Whether to output instructions also in binary form.
kLoggerOptionBinaryForm
=
0
,
//! Whether to output immediates as hexadecimal numbers.
kLoggerOptionHexImmediate
=
1
,
//! Whether to output displacements as hexadecimal numbers.
kLoggerOptionHexDisplacement
=
2
,
//! Count of logger options.
kLoggerOptionCount
=
3
};
// ============================================================================
// [asmjit::LoggerStyle]
// ============================================================================
//! Logger style.
ASMJIT_ENUM
(
LoggerStyle
)
{
kLoggerStyleDefault
=
0
,
kLoggerStyleDirective
=
1
,
kLoggerStyleLabel
=
2
,
kLoggerStyleData
=
3
,
kLoggerStyleComment
=
4
,
kLoggerStyleCount
=
5
};
// ============================================================================
// [asmjit::Logger]
// ============================================================================
//! Abstract logging class.
//!
//! This class can be inherited and reimplemented to fit into your logging
//! subsystem. When reimplementing use `Logger::log()` method to log into
//! a custom stream.
//!
//! This class also contain `_enabled` member that can be used to enable
//! or disable logging.
struct
ASMJIT_VCLASS
Logger
{
ASMJIT_NO_COPY
(
Logger
)
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! Create a `Logger` instance.
ASMJIT_API
Logger
();
//! Destroy the `Logger` instance.
ASMJIT_API
virtual
~
Logger
();
// --------------------------------------------------------------------------
// [Logging]
// --------------------------------------------------------------------------
//! Log output.
virtual
void
logString
(
uint32_t
style
,
const
char
*
buf
,
size_t
len
=
kInvalidIndex
)
=
0
;
//! Log formatter message (like sprintf) sending output to `logString()` method.
ASMJIT_API
void
logFormat
(
uint32_t
style
,
const
char
*
fmt
,
...);
//! Log binary data.
ASMJIT_API
void
logBinary
(
uint32_t
style
,
const
void
*
data
,
size_t
size
);
// --------------------------------------------------------------------------
// [Options]
// --------------------------------------------------------------------------
//! Get all logger options as a single integer.
ASMJIT_INLINE
uint32_t
getOptions
()
const
{
return
_options
;
}
//! Get the given logger option.
ASMJIT_INLINE
bool
getOption
(
uint32_t
id
)
const
{
ASMJIT_ASSERT
(
id
<
kLoggerOptionCount
);
return
static_cast
<
bool
>
((
_options
>>
id
)
&
0x1
);
}
//! Set the given logger option.
ASMJIT_API
void
setOption
(
uint32_t
id
,
bool
value
);
// --------------------------------------------------------------------------
// [Indentation]
// --------------------------------------------------------------------------
//! Get indentation.
ASMJIT_INLINE
const
char
*
getIndentation
()
const
{
return
_indentation
;
}
//! Set indentation.
ASMJIT_API
void
setIndentation
(
const
char
*
indentation
);
//! Reset indentation.
ASMJIT_INLINE
void
resetIndentation
()
{
setIndentation
(
NULL
);
}
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
//! Options, see \ref LoggerOption.
uint32_t
_options
;
//! Indentation.
char
_indentation
[
12
];
};
// ============================================================================
// [asmjit::FileLogger]
// ============================================================================
//! Logger that can log to standard C `FILE*` stream.
struct
ASMJIT_VCLASS
FileLogger
:
public
Logger
{
ASMJIT_NO_COPY
(
FileLogger
)
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! Create a new `FileLogger` that logs to a `FILE` stream.
ASMJIT_API
FileLogger
(
FILE
*
stream
=
NULL
);
//! Destroy the `FileLogger`.
ASMJIT_API
virtual
~
FileLogger
();
// --------------------------------------------------------------------------
// [Accessors]
// --------------------------------------------------------------------------
//! Get `FILE*` stream.
//!
//! \note Return value can be `NULL`.
ASMJIT_INLINE
FILE
*
getStream
()
const
{
return
_stream
;
}
//! 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_INLINE
void
setStream
(
FILE
*
stream
)
{
_stream
=
stream
;
}
// --------------------------------------------------------------------------
// [Logging]
// --------------------------------------------------------------------------
ASMJIT_API
virtual
void
logString
(
uint32_t
style
,
const
char
*
buf
,
size_t
len
=
kInvalidIndex
);
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
//! C file stream.
FILE
*
_stream
;
};
// ============================================================================
// [asmjit::StringLogger]
// ============================================================================
//! String logger.
struct
ASMJIT_VCLASS
StringLogger
:
public
Logger
{
ASMJIT_NO_COPY
(
StringLogger
)
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! Create new `StringLogger`.
ASMJIT_API
StringLogger
();
//! Destroy the `StringLogger`.
ASMJIT_API
virtual
~
StringLogger
();
// --------------------------------------------------------------------------
// [Accessors]
// --------------------------------------------------------------------------
//! Get `char*` pointer which represents the resulting string.
//!
//! The pointer is owned by `StringLogger`, it can't be modified or freed.
ASMJIT_INLINE
const
char
*
getString
()
const
{
return
_stringBuilder
.
getData
();
}
//! Clear the resulting string.
ASMJIT_INLINE
void
clearString
()
{
_stringBuilder
.
clear
();
}
// --------------------------------------------------------------------------
// [Logging]
// --------------------------------------------------------------------------
ASMJIT_API
virtual
void
logString
(
uint32_t
style
,
const
char
*
buf
,
size_t
len
=
kInvalidIndex
);
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
//! Output.
StringBuilder
_stringBuilder
;
};
//! \}
}
// asmjit namespace
// [Api-End]
#include "../apiend.h"
// [Guard]
#endif // !ASMJIT_DISABLE_LOGGER
#endif // _ASMJIT_BASE_LOGGER_H
libraries/asmjit/base/operand.cpp
0 → 100644
View file @
61d5cc0f
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Export]
#define ASMJIT_EXPORTS
// [Dependencies - AsmJit]
#include "../base/globals.h"
// [Api-Begin]
#include "../apibegin.h"
namespace
asmjit
{
// ============================================================================
// [asmjit::Operand]
// ============================================================================
// Prevent static initialization.
struct
Operand
{
uint8_t
op
;
uint8_t
size
;
uint8_t
reserved_2_1
;
uint8_t
reserved_3_1
;
uint32_t
id
;
uint64_t
reserved_8_8
;
};
ASMJIT_VAR
const
Operand
noOperand
;
const
Operand
noOperand
=
{
0
,
0
,
0
,
0
,
kInvalidValue
,
0
};
}
// asmjit namespace
// [Api-End]
#include "../apiend.h"
libraries/asmjit/base/operand.h
0 → 100644
View file @
61d5cc0f
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Guard]
#ifndef _ASMJIT_BASE_OPERAND_H
#define _ASMJIT_BASE_OPERAND_H
// [Dependencies - AsmJit]
#include "../base/intutil.h"
// [Api-Begin]
#include "../apibegin.h"
namespace
asmjit
{
// ============================================================================
// [Forward Declarations]
// ============================================================================
struct
Assembler
;
struct
Compiler
;
//! \addtogroup asmjit_base_general
//! \{
// ============================================================================
// [asmjit::OperandType]
// ============================================================================
//! Operand types that can be encoded in `Operand`.
ASMJIT_ENUM
(
OperandType
)
{
//! Invalid operand, used only internally (not initialized Operand).
kOperandTypeNone
=
0
,
//! Operand is a register.
kOperandTypeReg
=
1
,
//! Operand is a variable.
kOperandTypeVar
=
2
,
//! Operand is a memory.
kOperandTypeMem
=
3
,
//! Operand is an immediate value.
kOperandTypeImm
=
4
,
//! Operand is a label.
kOperandTypeLabel
=
5
};
// ============================================================================
// [asmjit::OperandId]
// ============================================================================
//! Operand id masks used to determine the operand type.
ASMJIT_ENUM
(
OperandId
)
{
//! Operand id refers to `Var`.
kOperandIdVar
=
0x80000000U
,
//! Operand id to real index mask.
kOperandIdNum
=
0x7FFFFFFFU
};
// ============================================================================
// [asmjit::RegClass]
// ============================================================================
//! Register class.
ASMJIT_ENUM
(
RegClass
)
{
//! Gp register class, compatible with all architectures.
kRegClassGp
=
0
};
// ============================================================================
// [asmjit::SizeDefs]
// ============================================================================
//! Common size of registers and pointers.
ASMJIT_ENUM
(
SizeDefs
)
{
//! 1 byte size (BYTE).
kSizeByte
=
1
,
//! 2 bytes size (WORD).
kSizeWord
=
2
,
//! 4 bytes size (DWORD).
kSizeDWord
=
4
,
//! 8 bytes size (QWORD).
kSizeQWord
=
8
,
//! 10 bytes size (TWORD).
kSizeTWord
=
10
,
//! 16 bytes size (OWORD / DQWORD).
kSizeOWord
=
16
,
//! 32 bytes size (YWORD / QQWORD).
kSizeYWord
=
32
};
// ============================================================================
// [asmjit::MemType]
// ============================================================================
//! Type of memory operand.
ASMJIT_ENUM
(
MemType
)
{
//! Memory operand is a combination of base register and optional index register
//! and displacement.
//!
//! The `Assembler` interprets `kMemTypeBaseIndex` and `kMemTypeStackIndex`
//! types the same way, but `Compiler` interprets `kMemTypeBaseIndex` as
//! `[base + index]` and `kMemTypeStackIndex` as `[stack(base) + index]`.
kMemTypeBaseIndex
=
0
,
//! Memory operand is a combination of variable's memory location,
//! optional index register and displacement.
//!
//! The `Assembler` interprets `kMemTypeBaseIndex` and `kMemTypeStackIndex`
//! types in the same way, but `Compiler` interprets `kMemTypeBaseIndex` as
//! `[base + index]` and `kMemTypeStackIndex` as `[stack(base) + index]`.
kMemTypeStackIndex
=
1
,
//! Memory operand refers to the memory location specified by a label.
kMemTypeLabel
=
2
,
//! Memory operand is an absolute memory location.
//!
//! Supported mostly by x86, truncated to a 32-bit value when running in
//! 64-bit mode (x64).
kMemTypeAbsolute
=
3
};
// ============================================================================
// [asmjit::Operand]
// ============================================================================
//! Operand can contain register, memory location, immediate, or label.
struct
Operand
{
// --------------------------------------------------------------------------
// [Structs]
// --------------------------------------------------------------------------
//! \internal
//!
//! Base operand data.
struct
BaseOp
{
//! Type of operand, see \ref OperandType.
uint8_t
op
;
//! Size of operand (register, address, immediate, or variable).
uint8_t
size
;
//! \internal
uint8_t
reserved_2_1
;
//! \internal
uint8_t
reserved_3_1
;
//! Operand id, identifier used by `Assembler` and `Compiler`.
//!
//! \note Uninitialized operand has always set id to `kInvalidValue`.
uint32_t
id
;
//! \internal
uint32_t
reserved_8_4
;
//! \internal
uint32_t
reserved_12_4
;
};
//! \internal
//!
//! Register or Variable operand data.
struct
VRegOp
{
//! Type of operand, `kOperandTypeReg`.
uint8_t
op
;
//! Size of register or variable.
uint8_t
size
;
union
{
//! Register code = (type << 8) | index.
uint16_t
code
;
//! Register type and index access.
struct
{
#if defined(ASMJIT_ARCH_LE)
//! Register index.
uint8_t
index
;
//! Register type.
uint8_t
type
;
#else
//! Register type.
uint8_t
type
;
//! Register index.
uint8_t
index
;
#endif
};
};
//! Variable id, used by `Compiler` to identify variables.
uint32_t
id
;
union
{
struct
{
//! Variable type.
uint32_t
vType
;
//! \internal
uint32_t
reserved_12_4
;
};
//! \internal
//!
//! This is not needed or used, it's just to force compiler to always
//! align this struct to 8-bytes (so the struct is compatible to others
//! when it comes to alignment). It should fix VS linker warning as well.
uint64_t
reserved8_8
;
};
};
//! \internal
//!
//! Memory or Variable operand data.
struct
VMemOp
{
//! Type of operand, `kOperandTypeMem`.
uint8_t
op
;
//! Size of the pointer in bytes.
uint8_t
size
;
//! Type of the memory operand, see `MemType`.
uint8_t
type
;
//! X86/X64 layout:
//! - segment [3 bits], see `X86Seg`.
//! - shift [2 bits], index register shift (0 to 3).
uint8_t
flags
;
//! Base register, variable or label id.
uint32_t
base
;
//! Index register or variable.
uint32_t
index
;
//! 32-bit displacement or absolute address.
int32_t
displacement
;
};
//! \internal
//!
//! Immediate operand data.
struct
ImmOp
{
//! Type of operand, `kOperandTypeImm`.
uint8_t
op
;
//! Size of immediate (or 0 to autodetect).
uint8_t
size
;
//! \internal
uint8_t
reserved_2_1
;
//! \internal
uint8_t
reserved_3_1
;
//! Operand id, always set to `kInvalidValue` (immediates don't have IDs).
uint32_t
id
;
union
{
//! 8x8-bit signed immediate values.
int8_t
_i8
[
8
];
//! 8x8-bit unsigned immediate values.
uint8_t
_u8
[
8
];
//! 4x16-bit signed immediate values.
int16_t
_i16
[
4
];
//! 4x16-bit unsigned immediate values.
uint16_t
_u16
[
4
];
//! 2x32-bit signed immediate values.
int32_t
_i32
[
2
];
//! 2x32-bit unsigned immediate values.
uint32_t
_u32
[
2
];
//! 1x64-bit signed immediate value.
int64_t
_i64
[
1
];
//! 1x64-bit unsigned immediate value.
uint64_t
_u64
[
1
];
//! 2x SP-FP values.
float
_f32
[
2
];
//! 1x DP-FP value.
double
_f64
[
1
];
}
value
;
};
//! \internal
//!
//! Label operand data.
struct
LabelOp
{
//! Type of operand, `kOperandTypeLabel`.
uint8_t
op
;
//! Always zero, labels don't have size.
uint8_t
size
;
//! \internal
uint8_t
reserved_2_1
;
//! \internal
uint8_t
reserved_3_1
;
//! Operand id (`kInvalidValue` if the label is not initialized by code
//! generator).
uint32_t
id
;
//! \internal
uint32_t
reserved_8_4
;
//! \internal
uint32_t
reserved_12_4
;
};
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! Create an uninitialized operand.
ASMJIT_INLINE
Operand
()
{
_init_packed_op_sz_b0_b1_id
(
kOperandTypeNone
,
0
,
0
,
0
,
kInvalidValue
);
_init_packed_d2_d3
(
0
,
0
);
}
//! Create a reference to `other` operand.
ASMJIT_INLINE
Operand
(
const
Operand
&
other
)
{
_init
(
other
);
}
explicit
ASMJIT_INLINE
Operand
(
const
_NoInit
&
)
{}
// --------------------------------------------------------------------------
// [Operand]
// --------------------------------------------------------------------------
//! Clone `Operand`.
ASMJIT_INLINE
Operand
clone
()
const
{
return
Operand
(
*
this
);
}
// --------------------------------------------------------------------------
// [Init & Copy]
// --------------------------------------------------------------------------
//! \internal
//!
//! Initialize operand to `other` (used by constructors).
ASMJIT_INLINE
void
_init
(
const
Operand
&
other
)
{
::
memcpy
(
this
,
&
other
,
sizeof
(
Operand
));
}
ASMJIT_INLINE
void
_init_packed_op_sz_b0_b1_id
(
uint32_t
op
,
uint32_t
sz
,
uint32_t
r0
,
uint32_t
r1
,
uint32_t
id
)
{
// This hack is not for performance, but to decrease the size of the binary
// generated when constructing AsmJit operands (mostly for third parties).
// Some compilers are not able to join four BYTE writes to a single DWORD
// write. Because the 'a', 'b', 'c' and 'd' variables are usually compile
// time constants the compiler can do a really nice job if they are joined
// by using bitwise operations.
_packed
[
0
].
setPacked_2x32
(
IntUtil
::
pack32_4x8
(
op
,
sz
,
r0
,
r1
),
id
);
}
ASMJIT_INLINE
void
_init_packed_op_sz_w0_id
(
uint32_t
op
,
uint32_t
sz
,
uint32_t
w0
,
uint32_t
id
)
{
_packed
[
0
].
setPacked_2x32
(
IntUtil
::
pack32_2x8_1x16
(
op
,
sz
,
w0
),
id
);
}
ASMJIT_INLINE
void
_init_packed_d0_d1
(
uint32_t
u0
,
uint32_t
u1
)
{
_packed
[
0
].
setPacked_2x32
(
u0
,
u1
);
}
ASMJIT_INLINE
void
_init_packed_d2_d3
(
uint32_t
u2
,
uint32_t
u3
)
{
_packed
[
1
].
setPacked_2x32
(
u2
,
u3
);
}
//! \internal
//!
//! Initialize operand to `other` (used by assign operators).
ASMJIT_INLINE
void
_copy
(
const
Operand
&
other
)
{
::
memcpy
(
this
,
&
other
,
sizeof
(
Operand
));
}
// --------------------------------------------------------------------------
// [Data]
// --------------------------------------------------------------------------
template
<
typename
T
>
ASMJIT_INLINE
T
&
getData
()
{
return
reinterpret_cast
<
T
&>
(
_base
);
}
template
<
typename
T
>
ASMJIT_INLINE
const
T
&
getData
()
const
{
return
reinterpret_cast
<
const
T
&>
(
_base
);
}
// --------------------------------------------------------------------------
// [Type]
// --------------------------------------------------------------------------
//! Get type of the operand, see \ref OperandType.
ASMJIT_INLINE
uint32_t
getOp
()
const
{
return
_base
.
op
;
}
//! Get whether the operand is none - `kOperandTypeNone`.
ASMJIT_INLINE
bool
isNone
()
const
{
return
(
_base
.
op
==
kOperandTypeNone
);
}
//! Get whether the operand is a register - `kOperandTypeReg`.
ASMJIT_INLINE
bool
isReg
()
const
{
return
(
_base
.
op
==
kOperandTypeReg
);
}
//! Get whether the operand is a variable - `kOperandTypeVar`.
ASMJIT_INLINE
bool
isVar
()
const
{
return
(
_base
.
op
==
kOperandTypeVar
);
}
//! Get whether the operand is a memory address - `kOperandTypeMem`.
ASMJIT_INLINE
bool
isMem
()
const
{
return
(
_base
.
op
==
kOperandTypeMem
);
}
//! Get whether the operand is an immediate value - `kOperandTypeImm`.
ASMJIT_INLINE
bool
isImm
()
const
{
return
(
_base
.
op
==
kOperandTypeImm
);
}
//! Get whether the operand is a label - `kOperandTypeLabel`.
ASMJIT_INLINE
bool
isLabel
()
const
{
return
(
_base
.
op
==
kOperandTypeLabel
);
}
// --------------------------------------------------------------------------
// [Type - Combined]
// --------------------------------------------------------------------------
//! Get register type.
ASMJIT_INLINE
uint32_t
getRegType
()
const
{
return
_vreg
.
type
;
}
//! Get register index.
ASMJIT_INLINE
uint32_t
getRegIndex
()
const
{
return
_vreg
.
index
;
}
//! Get whether the operand is register of `type`.
ASMJIT_INLINE
bool
isRegType
(
uint32_t
type
)
const
{
return
(
_packed
[
0
].
u32
[
0
]
&
IntUtil
::
pack32_2x8_1x16
(
0xFF
,
0
,
0xFF00
))
==
IntUtil
::
pack32_2x8_1x16
(
kOperandTypeReg
,
0
,
(
type
<<
8
));
}
//! Get whether the operand is register and of `type` and `index`.
ASMJIT_INLINE
bool
isRegCode
(
uint32_t
type
,
uint32_t
index
)
const
{
return
(
_packed
[
0
].
u32
[
0
]
&
IntUtil
::
pack32_2x8_1x16
(
0xFF
,
0
,
0xFFFF
))
==
IntUtil
::
pack32_2x8_1x16
(
kOperandTypeReg
,
0
,
(
type
<<
8
)
+
index
);
}
//! Get whether the operand is a register or memory.
ASMJIT_INLINE
bool
isRegOrMem
()
const
{
ASMJIT_ASSERT
(
kOperandTypeReg
==
1
);
ASMJIT_ASSERT
(
kOperandTypeMem
==
3
);
return
(
static_cast
<
uint32_t
>
(
_base
.
op
)
|
0x2U
)
==
0x3U
;
}
//! Get whether the operand is variable or memory.
ASMJIT_INLINE
bool
isVarOrMem
()
const
{
ASMJIT_ASSERT
(
kOperandTypeVar
==
2
);
ASMJIT_ASSERT
(
kOperandTypeMem
==
3
);
return
(
static_cast
<
uint32_t
>
(
_base
.
op
)
-
2U
)
<=
1
;
}
// --------------------------------------------------------------------------
// [Size]
// --------------------------------------------------------------------------
//! Get size of the operand in bytes.
ASMJIT_INLINE
uint32_t
getSize
()
const
{
return
_base
.
size
;
}
// --------------------------------------------------------------------------
// [Id]
// --------------------------------------------------------------------------
//! Get operand id.
//!
//! Operand id's are used internally by `Assembler` and `Compiler`.
//!
//! There is no way to change or remove operand id. Unneeded operands can be
//! simply reassigned by `operator=`.
ASMJIT_INLINE
uint32_t
getId
()
const
{
return
_base
.
id
;
}
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
union
{
//! Base data.
BaseOp
_base
;
//! Register or variable data.
VRegOp
_vreg
;
//! Memory data.
VMemOp
_vmem
;
//! Immediate data.
ImmOp
_imm
;
//! Label data.
LabelOp
_label
;
//! Packed operand as two 64-bit integers.
UInt64
_packed
[
2
];
};
};
// ============================================================================
// [asmjit::OperandUtil]
// ============================================================================
//! Operand utilities.
struct
OperandUtil
{
//! Make variable id.
static
ASMJIT_INLINE
uint32_t
makeVarId
(
uint32_t
id
)
{
return
id
|
kOperandIdVar
;
}
//! Make label id.
static
ASMJIT_INLINE
uint32_t
makeLabelId
(
uint32_t
id
)
{
return
id
;
}
//! Strip variable id bit so it becomes a pure index to `VarData[]` array.
static
ASMJIT_INLINE
uint32_t
stripVarId
(
uint32_t
id
)
{
return
id
&
0x7FFFFFFFU
;
}
//! Get whether the id refers to `Var`.
//!
//! \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
)
{
return
static_cast
<
int32_t
>
(
id
)
<
-
1
;
}
//! Get whether the id refers to `Label`.
//!
//! \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
;
}
};
// ============================================================================
// [asmjit::Reg]
// ============================================================================
//! Base class for all register operands.
struct
Reg
:
public
Operand
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! Create a dummy base register.
ASMJIT_INLINE
Reg
()
:
Operand
(
NoInit
)
{
_init_packed_op_sz_w0_id
(
kOperandTypeReg
,
0
,
(
kInvalidReg
<<
8
)
+
kInvalidReg
,
kInvalidValue
);
_init_packed_d2_d3
(
kInvalidVar
,
0
);
}
//! Create a new base register.
ASMJIT_INLINE
Reg
(
uint32_t
type
,
uint32_t
index
,
uint32_t
size
)
:
Operand
(
NoInit
)
{
_init_packed_op_sz_w0_id
(
kOperandTypeReg
,
size
,
(
type
<<
8
)
+
index
,
kInvalidValue
);
_init_packed_d2_d3
(
kInvalidVar
,
0
);
}
//! Create a new reference to `other`.
ASMJIT_INLINE
Reg
(
const
Reg
&
other
)
:
Operand
(
other
)
{}
//! Create a new reference to `other` and change the index to `index`.
ASMJIT_INLINE
Reg
(
const
Reg
&
other
,
uint32_t
index
)
:
Operand
(
other
)
{
_vreg
.
index
=
static_cast
<
uint8_t
>
(
index
);
}
explicit
ASMJIT_INLINE
Reg
(
const
_NoInit
&
)
:
Operand
(
NoInit
)
{}
// --------------------------------------------------------------------------
// [Reg Specific]
// --------------------------------------------------------------------------
//! Clone `Reg` operand.
ASMJIT_INLINE
Reg
clone
()
const
{
return
Reg
(
*
this
);
}
//! Get whether register code is equal to `type`.
ASMJIT_INLINE
bool
isRegType
(
uint32_t
type
)
const
{
return
_vreg
.
type
==
type
;
}
//! Get whether register code is equal to `type`.
ASMJIT_INLINE
bool
isRegCode
(
uint32_t
code
)
const
{
return
_vreg
.
code
==
code
;
}
//! Get whether register code is equal to `type`.
ASMJIT_INLINE
bool
isRegCode
(
uint32_t
type
,
uint32_t
index
)
const
{
return
_vreg
.
code
==
(
type
<<
8
)
+
index
;
}
//! Get register code that equals to '(type << 8) + index'.
ASMJIT_INLINE
uint32_t
getRegCode
()
const
{
return
_vreg
.
code
;
}
//! Get register type.
ASMJIT_INLINE
uint32_t
getRegType
()
const
{
return
_vreg
.
type
;
}
//! Get register index.
ASMJIT_INLINE
uint32_t
getRegIndex
()
const
{
return
_vreg
.
index
;
}
#define ASMJIT_REG_OP(_Type_) \
ASMJIT_INLINE _Type_ clone() const { \
return _Type_(*this); \
} \
\
/*! Set register `size`. */
\
ASMJIT_INLINE _Type_& setSize(uint32_t size) { \
_vreg.size = static_cast<uint8_t>(size); \
return *this; \
} \
\
/*! Set register `code`. */
\
ASMJIT_INLINE _Type_& setCode(uint32_t code) { \
_vreg.code = static_cast<uint16_t>(code); \
return *this; \
} \
\
/*! Set register `type` and `index`. */
\
ASMJIT_INLINE _Type_& setCode(uint32_t type, uint32_t index) { \
_vreg.type = static_cast<uint8_t>(type); \
_vreg.index = static_cast<uint8_t>(index); \
return *this; \
} \
\
/*! Set register `type`. */
\
ASMJIT_INLINE _Type_& setType(uint32_t type) { \
_vreg.type = static_cast<uint8_t>(type); \
return *this; \
} \
\
/*! Set register `index`. */
\
ASMJIT_INLINE _Type_& setIndex(uint32_t index) { \
_vreg.index = static_cast<uint8_t>(index); \
return *this; \
} \
\
ASMJIT_INLINE _Type_& operator=(const _Type_& other) { _copy(other); return *this; } \
\
ASMJIT_INLINE bool operator==(const _Type_& other) const { return _packed[0].u32[0] == other._packed[0].u32[0]; } \
ASMJIT_INLINE bool operator!=(const _Type_& other) const { return !operator==(other); }
};
// ============================================================================
// [asmjit::BaseMem]
// ============================================================================
//! Base class for all memory operands.
struct
BaseMem
:
public
Operand
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
ASMJIT_INLINE
BaseMem
()
:
Operand
(
NoInit
)
{
reset
();
}
ASMJIT_INLINE
BaseMem
(
const
BaseMem
&
other
)
:
Operand
(
other
)
{}
explicit
ASMJIT_INLINE
BaseMem
(
const
_NoInit
&
)
:
Operand
(
NoInit
)
{}
// --------------------------------------------------------------------------
// [BaseMem Specific]
// --------------------------------------------------------------------------
//! Clone `BaseMem` operand.
ASMJIT_INLINE
BaseMem
clone
()
const
{
return
BaseMem
(
*
this
);
}
//! Reset `BaseMem` operand.
ASMJIT_INLINE
void
reset
()
{
_init_packed_op_sz_b0_b1_id
(
kOperandTypeMem
,
0
,
kMemTypeBaseIndex
,
0
,
kInvalidValue
);
_init_packed_d2_d3
(
kInvalidValue
,
0
);
}
//! Get the type of the memory operand, see `MemType`.
ASMJIT_INLINE
uint32_t
getMemType
()
const
{
return
_vmem
.
type
;
}
//! Get whether the type of the memory operand is either `kMemTypeBaseIndex`
//! or `kMemTypeStackIndex`.
ASMJIT_INLINE
bool
isBaseIndexType
()
const
{
return
_vmem
.
type
<=
kMemTypeStackIndex
;
}
//! Get whether the memory operand has base register.
ASMJIT_INLINE
bool
hasBase
()
const
{
return
_vmem
.
base
!=
kInvalidValue
;
}
//! Get memory operand base id, or `kInvalidValue`.
ASMJIT_INLINE
uint32_t
getBase
()
const
{
return
_vmem
.
base
;
}
//! Set memory operand size.
ASMJIT_INLINE
BaseMem
&
setSize
(
uint32_t
size
)
{
_vmem
.
size
=
static_cast
<
uint8_t
>
(
size
);
return
*
this
;
}
//! Get memory operand relative displacement.
ASMJIT_INLINE
int32_t
getDisplacement
()
const
{
return
_vmem
.
displacement
;
}
//! Set memory operand relative displacement.
ASMJIT_INLINE
BaseMem
&
setDisplacement
(
int32_t
disp
)
{
_vmem
.
displacement
=
disp
;
return
*
this
;
}
// --------------------------------------------------------------------------
// [Operator Overload]
// --------------------------------------------------------------------------
ASMJIT_INLINE
BaseMem
&
operator
=
(
const
BaseMem
&
other
)
{
_copy
(
other
);
return
*
this
;
}
ASMJIT_INLINE
bool
operator
==
(
const
BaseMem
&
other
)
const
{
return
(
_packed
[
0
]
==
other
.
_packed
[
0
])
&
(
_packed
[
1
]
==
other
.
_packed
[
1
]);
}
ASMJIT_INLINE
bool
operator
!=
(
const
BaseMem
&
other
)
const
{
return
!
(
*
this
==
other
);
}
};
// ============================================================================
// [asmjit::Imm]
// ============================================================================
//! Immediate operand.
//!
//! Immediate operand is usually part of instruction itself. It's inlined after
//! or before the instruction opcode. Immediates can be only signed or unsigned
//! integers.
//!
//! To create immediate operand use `imm()` or `imm_u()` non-members or `Imm`
//! constructors.
struct
Imm
:
public
Operand
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! Create a new immediate value (initial value is 0).
Imm
()
:
Operand
(
NoInit
)
{
_init_packed_op_sz_b0_b1_id
(
kOperandTypeImm
,
0
,
0
,
0
,
kInvalidValue
);
_imm
.
value
.
_i64
[
0
]
=
0
;
}
//! Create a new signed immediate value, assigning the value to `val`.
explicit
Imm
(
int64_t
val
)
:
Operand
(
NoInit
)
{
_init_packed_op_sz_b0_b1_id
(
kOperandTypeImm
,
0
,
0
,
0
,
kInvalidValue
);
_imm
.
value
.
_i64
[
0
]
=
val
;
}
//! Create a new immediate value from `other`.
ASMJIT_INLINE
Imm
(
const
Imm
&
other
)
:
Operand
(
other
)
{}
explicit
ASMJIT_INLINE
Imm
(
const
_NoInit
&
)
:
Operand
(
NoInit
)
{}
// --------------------------------------------------------------------------
// [Immediate Specific]
// --------------------------------------------------------------------------
//! Clone `Imm` operand.
ASMJIT_INLINE
Imm
clone
()
const
{
return
Imm
(
*
this
);
}
//! Get whether the immediate can be casted to 8-bit signed integer.
ASMJIT_INLINE
bool
isInt8
()
const
{
return
IntUtil
::
isInt8
(
_imm
.
value
.
_i64
[
0
]);
}
//! Get whether the immediate can be casted to 8-bit unsigned integer.
ASMJIT_INLINE
bool
isUInt8
()
const
{
return
IntUtil
::
isUInt8
(
_imm
.
value
.
_i64
[
0
]);
}
//! Get whether the immediate can be casted to 16-bit signed integer.
ASMJIT_INLINE
bool
isInt16
()
const
{
return
IntUtil
::
isInt16
(
_imm
.
value
.
_i64
[
0
]);
}
//! Get whether the immediate can be casted to 16-bit unsigned integer.
ASMJIT_INLINE
bool
isUInt16
()
const
{
return
IntUtil
::
isUInt16
(
_imm
.
value
.
_i64
[
0
]);
}
//! Get whether the immediate can be casted to 32-bit signed integer.
ASMJIT_INLINE
bool
isInt32
()
const
{
return
IntUtil
::
isInt32
(
_imm
.
value
.
_i64
[
0
]);
}
//! Get whether the immediate can be casted to 32-bit unsigned integer.
ASMJIT_INLINE
bool
isUInt32
()
const
{
return
IntUtil
::
isUInt32
(
_imm
.
value
.
_i64
[
0
]);
}
//! Get immediate value as 8-bit signed integer.
ASMJIT_INLINE
int8_t
getInt8
()
const
{
return
_imm
.
value
.
_i8
[
_ASMJIT_ARCH_INDEX
(
8
,
0
)];
}
//! Get immediate value as 8-bit unsigned integer.
ASMJIT_INLINE
uint8_t
getUInt8
()
const
{
return
_imm
.
value
.
_u8
[
_ASMJIT_ARCH_INDEX
(
8
,
0
)];
}
//! Get immediate value as 16-bit signed integer.
ASMJIT_INLINE
int16_t
getInt16
()
const
{
return
_imm
.
value
.
_i16
[
_ASMJIT_ARCH_INDEX
(
4
,
0
)];
}
//! Get immediate value as 16-bit unsigned integer.
ASMJIT_INLINE
uint16_t
getUInt16
()
const
{
return
_imm
.
value
.
_u16
[
_ASMJIT_ARCH_INDEX
(
4
,
0
)];
}
//! Get immediate value as 32-bit signed integer.
ASMJIT_INLINE
int32_t
getInt32
()
const
{
return
_imm
.
value
.
_i32
[
_ASMJIT_ARCH_INDEX
(
2
,
0
)];
}
//! Get immediate value as 32-bit unsigned integer.
ASMJIT_INLINE
uint32_t
getUInt32
()
const
{
return
_imm
.
value
.
_u32
[
_ASMJIT_ARCH_INDEX
(
2
,
0
)];
}
//! Get immediate value as 64-bit signed integer.
ASMJIT_INLINE
int64_t
getInt64
()
const
{
return
_imm
.
value
.
_i64
[
0
];
}
//! Get immediate value as 64-bit unsigned integer.
ASMJIT_INLINE
uint64_t
getUInt64
()
const
{
return
_imm
.
value
.
_u64
[
0
];
}
//! Get immediate value as `intptr_t`.
ASMJIT_INLINE
intptr_t
getIntPtr
()
const
{
if
(
sizeof
(
intptr_t
)
==
sizeof
(
int64_t
))
return
static_cast
<
intptr_t
>
(
getInt64
());
else
return
static_cast
<
intptr_t
>
(
getInt32
());
}
//! Get immediate value as `uintptr_t`.
ASMJIT_INLINE
uintptr_t
getUIntPtr
()
const
{
if
(
sizeof
(
uintptr_t
)
==
sizeof
(
uint64_t
))
return
static_cast
<
uintptr_t
>
(
getUInt64
());
else
return
static_cast
<
uintptr_t
>
(
getUInt32
());
}
//! Get low 32-bit signed integer.
ASMJIT_INLINE
int32_t
getInt32Lo
()
const
{
return
_imm
.
value
.
_i32
[
_ASMJIT_ARCH_INDEX
(
2
,
0
)];
}
//! Get low 32-bit signed integer.
ASMJIT_INLINE
uint32_t
getUInt32Lo
()
const
{
return
_imm
.
value
.
_u32
[
_ASMJIT_ARCH_INDEX
(
2
,
0
)];
}
//! Get high 32-bit signed integer.
ASMJIT_INLINE
int32_t
getInt32Hi
()
const
{
return
_imm
.
value
.
_i32
[
_ASMJIT_ARCH_INDEX
(
2
,
1
)];
}
//! Get high 32-bit signed integer.
ASMJIT_INLINE
uint32_t
getUInt32Hi
()
const
{
return
_imm
.
value
.
_u32
[
_ASMJIT_ARCH_INDEX
(
2
,
1
)];
}
//! Set immediate value to 8-bit signed integer `val`.
ASMJIT_INLINE
Imm
&
setInt8
(
int8_t
val
)
{
if
(
kArchHost64Bit
)
{
_imm
.
value
.
_i64
[
0
]
=
static_cast
<
int64_t
>
(
val
);
}
else
{
int32_t
val32
=
static_cast
<
int32_t
>
(
val
);
_imm
.
value
.
_i32
[
_ASMJIT_ARCH_INDEX
(
2
,
0
)]
=
val32
;
_imm
.
value
.
_i32
[
_ASMJIT_ARCH_INDEX
(
2
,
1
)]
=
val32
>>
31
;
}
return
*
this
;
}
//! Set immediate value to 8-bit unsigned integer `val`.
ASMJIT_INLINE
Imm
&
setUInt8
(
uint8_t
val
)
{
if
(
kArchHost64Bit
)
{
_imm
.
value
.
_u64
[
0
]
=
static_cast
<
uint64_t
>
(
val
);
}
else
{
_imm
.
value
.
_u32
[
_ASMJIT_ARCH_INDEX
(
2
,
0
)]
=
static_cast
<
uint32_t
>
(
val
);
_imm
.
value
.
_u32
[
_ASMJIT_ARCH_INDEX
(
2
,
1
)]
=
0
;
}
return
*
this
;
}
//! Set immediate value to 16-bit signed integer `val`.
ASMJIT_INLINE
Imm
&
setInt16
(
int16_t
val
)
{
if
(
kArchHost64Bit
)
{
_imm
.
value
.
_i64
[
0
]
=
static_cast
<
int64_t
>
(
val
);
}
else
{
int32_t
val32
=
static_cast
<
int32_t
>
(
val
);
_imm
.
value
.
_i32
[
_ASMJIT_ARCH_INDEX
(
2
,
0
)]
=
val32
;
_imm
.
value
.
_i32
[
_ASMJIT_ARCH_INDEX
(
2
,
1
)]
=
val32
>>
31
;
}
return
*
this
;
}
//! Set immediate value to 16-bit unsigned integer `val`.
ASMJIT_INLINE
Imm
&
setUInt16
(
uint16_t
val
)
{
if
(
kArchHost64Bit
)
{
_imm
.
value
.
_u64
[
0
]
=
static_cast
<
uint64_t
>
(
val
);
}
else
{
_imm
.
value
.
_u32
[
_ASMJIT_ARCH_INDEX
(
2
,
0
)]
=
static_cast
<
uint32_t
>
(
val
);
_imm
.
value
.
_u32
[
_ASMJIT_ARCH_INDEX
(
2
,
1
)]
=
0
;
}
return
*
this
;
}
//! Set immediate value to 32-bit signed integer `val`.
ASMJIT_INLINE
Imm
&
setInt32
(
int32_t
val
)
{
if
(
kArchHost64Bit
)
{
_imm
.
value
.
_i64
[
0
]
=
static_cast
<
int64_t
>
(
val
);
}
else
{
_imm
.
value
.
_i32
[
_ASMJIT_ARCH_INDEX
(
2
,
0
)]
=
val
;
_imm
.
value
.
_i32
[
_ASMJIT_ARCH_INDEX
(
2
,
1
)]
=
val
>>
31
;
}
return
*
this
;
}
//! Set immediate value to 32-bit unsigned integer `val`.
ASMJIT_INLINE
Imm
&
setUInt32
(
uint32_t
val
)
{
if
(
kArchHost64Bit
)
{
_imm
.
value
.
_u64
[
0
]
=
static_cast
<
uint64_t
>
(
val
);
}
else
{
_imm
.
value
.
_u32
[
_ASMJIT_ARCH_INDEX
(
2
,
0
)]
=
val
;
_imm
.
value
.
_u32
[
_ASMJIT_ARCH_INDEX
(
2
,
1
)]
=
0
;
}
return
*
this
;
}
//! Set immediate value to 64-bit signed integer `val`.
ASMJIT_INLINE
Imm
&
setInt64
(
int64_t
val
)
{
_imm
.
value
.
_i64
[
0
]
=
val
;
return
*
this
;
}
//! Set immediate value to 64-bit unsigned integer `val`.
ASMJIT_INLINE
Imm
&
setUInt64
(
uint64_t
val
)
{
_imm
.
value
.
_u64
[
0
]
=
val
;
return
*
this
;
}
//! Set immediate value to intptr_t `val`.
ASMJIT_INLINE
Imm
&
setIntPtr
(
intptr_t
val
)
{
_imm
.
value
.
_i64
[
0
]
=
static_cast
<
int64_t
>
(
val
);
return
*
this
;
}
//! Set immediate value to uintptr_t `val`.
ASMJIT_INLINE
Imm
&
setUIntPtr
(
uintptr_t
val
)
{
_imm
.
value
.
_u64
[
0
]
=
static_cast
<
uint64_t
>
(
val
);
return
*
this
;
}
//! Set immediate value as unsigned type to `val`.
ASMJIT_INLINE
Imm
&
setPtr
(
void
*
p
)
{
return
setIntPtr
((
intptr_t
)
p
);
}
// --------------------------------------------------------------------------
// [Float]
// --------------------------------------------------------------------------
ASMJIT_INLINE
Imm
&
setFloat
(
float
f
)
{
_imm
.
value
.
_f32
[
_ASMJIT_ARCH_INDEX
(
2
,
0
)]
=
f
;
_imm
.
value
.
_u32
[
_ASMJIT_ARCH_INDEX
(
2
,
1
)]
=
0
;
return
*
this
;
}
ASMJIT_INLINE
Imm
&
setDouble
(
double
d
)
{
_imm
.
value
.
_f64
[
0
]
=
d
;
return
*
this
;
}
// --------------------------------------------------------------------------
// [Truncate]
// --------------------------------------------------------------------------
ASMJIT_INLINE
Imm
&
truncateTo8Bits
()
{
if
(
kArchHost64Bit
)
{
_imm
.
value
.
_u64
[
0
]
&=
static_cast
<
uint64_t
>
(
0x000000FFU
);
}
else
{
_imm
.
value
.
_u32
[
_ASMJIT_ARCH_INDEX
(
2
,
0
)]
&=
0x000000FFU
;
_imm
.
value
.
_u32
[
_ASMJIT_ARCH_INDEX
(
2
,
1
)]
=
0
;
}
return
*
this
;
}
ASMJIT_INLINE
Imm
&
truncateTo16Bits
()
{
if
(
kArchHost64Bit
)
{
_imm
.
value
.
_u64
[
0
]
&=
static_cast
<
uint64_t
>
(
0x0000FFFFU
);
}
else
{
_imm
.
value
.
_u32
[
_ASMJIT_ARCH_INDEX
(
2
,
0
)]
&=
0x0000FFFFU
;
_imm
.
value
.
_u32
[
_ASMJIT_ARCH_INDEX
(
2
,
1
)]
=
0
;
}
return
*
this
;
}
ASMJIT_INLINE
Imm
&
truncateTo32Bits
()
{
_imm
.
value
.
_u32
[
_ASMJIT_ARCH_INDEX
(
2
,
1
)]
=
0
;
return
*
this
;
}
// --------------------------------------------------------------------------
// [Operator Overload]
// --------------------------------------------------------------------------
//! Assign `other` to the immediate operand.
ASMJIT_INLINE
Imm
&
operator
=
(
const
Imm
&
other
)
{
_copy
(
other
);
return
*
this
;
}
};
// ============================================================================
// [asmjit::Label]
// ============================================================================
//! Label (jump target or data location).
//!
//! Label represents a location in code typically used as jump targets, but may
//! be also reference data or static variables. Label has to be explicitly
//! created by a code-generator by calling `CodeGen::newLabel()` where `CodeGen`
//! is your code generator, which derives from `Assembler` or `Compiler`.
//!
//! Example of using labels:
//!
//! ~~~
//! // Create Assembler/Compiler.
//! host::Assembler a;
//!
//! // Create Label instance.
//! Label L_1(a);
//!
//! // ... your code ...
//!
//! // Using label.
//! a.jump(L_1);
//!
//! // ... your code ...
//!
//! // Bind label to the current position, see `CodeGen::bind()`.
//! a.bind(L_1);
//! ~~~
struct
Label
:
public
Operand
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! Create new, unassociated label.
ASMJIT_INLINE
Label
()
:
Operand
(
NoInit
)
{
reset
();
}
explicit
ASMJIT_INLINE
Label
(
uint32_t
id
)
:
Operand
(
NoInit
)
{
_init_packed_op_sz_b0_b1_id
(
kOperandTypeLabel
,
0
,
0
,
0
,
id
);
_init_packed_d2_d3
(
0
,
0
);
}
//! Create new initialized label.
explicit
ASMJIT_INLINE
Label
(
Assembler
&
a
);
//! Create new initialized label.
explicit
ASMJIT_INLINE
Label
(
Compiler
&
c
);
//! Create reference to another label.
ASMJIT_INLINE
Label
(
const
Label
&
other
)
:
Operand
(
other
)
{}
explicit
ASMJIT_INLINE
Label
(
const
_NoInit
&
)
:
Operand
(
NoInit
)
{}
// --------------------------------------------------------------------------
// [Reset]
// --------------------------------------------------------------------------
ASMJIT_INLINE
void
reset
()
{
_init_packed_op_sz_b0_b1_id
(
kOperandTypeLabel
,
0
,
0
,
0
,
kInvalidValue
);
_init_packed_d2_d3
(
0
,
0
);
}
// --------------------------------------------------------------------------
// [Label Specific]
// --------------------------------------------------------------------------
//! Get whether the label has been initialized by `Assembler` or `Compiler`.
ASMJIT_INLINE
bool
isInitialized
()
const
{
return
_label
.
id
!=
kInvalidValue
;
}
// --------------------------------------------------------------------------
// [Operator Overload]
// --------------------------------------------------------------------------
ASMJIT_INLINE
Label
&
operator
=
(
const
Label
&
other
)
{
_copy
(
other
);
return
*
this
;
}
ASMJIT_INLINE
bool
operator
==
(
const
Label
&
other
)
const
{
return
_base
.
id
==
other
.
_base
.
id
;
}
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
// [Api-End]
#include "../apiend.h"
// [Guard]
#endif // _ASMJIT_BASE_OPERAND_H
Prev
1
2
3
4
5
6
7
…
12
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment