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
751ff079
Commit
751ff079
authored
Sep 30, 2014
by
peastman
Browse files
Merge pull request #630 from peastman/jit
JIT compilation for custom forces in CPU platform
parents
77ea3bb6
5a98c0a1
Changes
68
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
2375 additions
and
158 deletions
+2375
-158
libraries/asmjit/x86/x86operand.cpp
libraries/asmjit/x86/x86operand.cpp
+85
-0
libraries/asmjit/x86/x86operand.h
libraries/asmjit/x86/x86operand.h
+1531
-0
libraries/asmjit/x86/x86operand_regs.cpp
libraries/asmjit/x86/x86operand_regs.cpp
+188
-0
libraries/asmjit/x86/x86scheduler.cpp
libraries/asmjit/x86/x86scheduler.cpp
+94
-0
libraries/asmjit/x86/x86scheduler_p.h
libraries/asmjit/x86/x86scheduler_p.h
+63
-0
libraries/lepton/include/lepton/CompiledExpression.h
libraries/lepton/include/lepton/CompiledExpression.h
+10
-0
libraries/lepton/src/CompiledExpression.cpp
libraries/lepton/src/CompiledExpression.cpp
+371
-149
tests/TestParser.cpp
tests/TestParser.cpp
+33
-9
No files found.
libraries/asmjit/x86/x86operand.cpp
0 → 100644
View file @
751ff079
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Export]
#define ASMJIT_EXPORTS
// [Guard]
#include "../build.h"
#if defined(ASMJIT_BUILD_X86) || defined(ASMJIT_BUILD_X64)
// [Dependencies - AsmJit]
#include "../x86/x86operand.h"
// [Api-Begin]
#include "../apibegin.h"
namespace
asmjit
{
namespace
x86
{
// ============================================================================
// [asmjit::X86Mem - abs[]]
// ============================================================================
X86Mem
ptr_abs
(
Ptr
pAbs
,
int32_t
disp
,
uint32_t
size
)
{
X86Mem
m
(
NoInit
);
m
.
_init_packed_op_sz_b0_b1_id
(
kOperandTypeMem
,
size
,
kMemTypeAbsolute
,
0
,
kInvalidValue
);
m
.
_vmem
.
index
=
kInvalidValue
;
m
.
_vmem
.
displacement
=
static_cast
<
int32_t
>
((
intptr_t
)(
pAbs
+
disp
));
return
m
;
}
X86Mem
ptr_abs
(
Ptr
pAbs
,
const
X86Reg
&
index
,
uint32_t
shift
,
int32_t
disp
,
uint32_t
size
)
{
X86Mem
m
(
NoInit
);
uint32_t
flags
=
shift
<<
kX86MemShiftIndex
;
if
(
index
.
isGp
())
flags
|=
X86Mem
::
_getGpdFlags
(
index
);
else
if
(
index
.
isXmm
())
flags
|=
kX86MemVSibXmm
<<
kX86MemVSibIndex
;
else
if
(
index
.
isYmm
())
flags
|=
kX86MemVSibYmm
<<
kX86MemVSibIndex
;
m
.
_init_packed_op_sz_b0_b1_id
(
kOperandTypeMem
,
size
,
kMemTypeAbsolute
,
flags
,
kInvalidValue
);
m
.
_vmem
.
index
=
index
.
getRegIndex
();
m
.
_vmem
.
displacement
=
static_cast
<
int32_t
>
((
intptr_t
)(
pAbs
+
disp
));
return
m
;
}
#if !defined(ASMJIT_DISABLE_COMPILER)
X86Mem
ptr_abs
(
Ptr
pAbs
,
const
X86Var
&
index
,
uint32_t
shift
,
int32_t
disp
,
uint32_t
size
)
{
X86Mem
m
(
NoInit
);
uint32_t
flags
=
shift
<<
kX86MemShiftIndex
;
const
Var
&
index_
=
reinterpret_cast
<
const
Var
&>
(
index
);
uint32_t
indexRegType
=
index_
.
getRegType
();
if
(
indexRegType
<=
kX86RegTypeGpq
)
flags
|=
X86Mem
::
_getGpdFlags
(
reinterpret_cast
<
const
Var
&>
(
index
));
else
if
(
indexRegType
==
kX86RegTypeXmm
)
flags
|=
kX86MemVSibXmm
<<
kX86MemVSibIndex
;
else
if
(
indexRegType
==
kX86RegTypeYmm
)
flags
|=
kX86MemVSibYmm
<<
kX86MemVSibIndex
;
m
.
_init_packed_op_sz_b0_b1_id
(
kOperandTypeMem
,
size
,
kMemTypeAbsolute
,
flags
,
kInvalidValue
);
m
.
_vmem
.
index
=
index_
.
getId
();
m
.
_vmem
.
displacement
=
static_cast
<
int32_t
>
((
intptr_t
)(
pAbs
+
disp
));
return
m
;
}
#endif // !ASMJIT_DISABLE_COMPILER
}
// x86 namespace
}
// asmjit namespace
// [Api-End]
#include "../apiend.h"
// [Guard]
#endif // ASMJIT_BUILD_X86 || ASMJIT_BUILD_X64
libraries/asmjit/x86/x86operand.h
0 → 100644
View file @
751ff079
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Guard]
#ifndef _ASMJIT_X86_X86OPERAND_H
#define _ASMJIT_X86_X86OPERAND_H
// [Dependencies - AsmJit]
#include "../base/assembler.h"
#include "../base/compiler.h"
#include "../base/globals.h"
#include "../base/intutil.h"
#include "../base/operand.h"
#include "../base/vectypes.h"
// [Api-Begin]
#include "../apibegin.h"
//! \internal
//!
//! Internal macro to get an operand ID casting it to `Operand`. Basically
//! allows to get an id of operand that has been just 'typedef'ed.
#define _OP_ID(_Op_) reinterpret_cast<const Operand&>(_Op_).getId()
namespace
asmjit
{
// ============================================================================
// [Forward Declarations]
// ============================================================================
struct
X86Reg
;
struct
X86GpReg
;
struct
X86FpReg
;
struct
X86MmReg
;
struct
X86XmmReg
;
struct
X86YmmReg
;
struct
X86SegReg
;
#if !defined(ASMJIT_DISABLE_COMPILER)
struct
X86Var
;
struct
X86GpVar
;
struct
X86MmVar
;
struct
X86XmmVar
;
struct
X86YmmVar
;
#endif // !ASMJIT_DISABLE_COMPILER
//! \addtogroup asmjit_x86_general
//! \{
// ============================================================================
// [asmjit::kX86RegClass]
// ============================================================================
//! X86/X64 variable class.
ASMJIT_ENUM
(
kX86RegClass
)
{
//! X86/X64 Gp register class (compatible with universal \ref kRegClassGp).
kX86RegClassGp
=
kRegClassGp
,
//! X86/X64 Fp register class.
kX86RegClassFp
=
1
,
//! X86/X64 Mm register class.
kX86RegClassMm
=
2
,
//! X86/X64 Xmm/Ymm/Zmm register class.
kX86RegClassXyz
=
3
,
//! Count of X86/X64 register classes.
kX86RegClassCount
=
4
};
// ============================================================================
// [asmjit::kX86RegType]
// ============================================================================
//! X86/X64 register type.
ASMJIT_ENUM
(
kX86RegType
)
{
//! Gpb-lo register (AL, BL, CL, DL, ...).
kX86RegTypeGpbLo
=
0x01
,
//! Gpb-hi register (AH, BH, CH, DH only).
kX86RegTypeGpbHi
=
0x02
,
//! \internal
//!
//! Gpb-hi register patched to native index (4-7).
_kX86RegTypePatchedGpbHi
=
kX86RegTypeGpbLo
|
kX86RegTypeGpbHi
,
//! Gpw register.
kX86RegTypeGpw
=
0x10
,
//! Gpd register.
kX86RegTypeGpd
=
0x20
,
//! Gpq register.
kX86RegTypeGpq
=
0x30
,
//! Fp register.
kX86RegTypeFp
=
0x50
,
//! Mm register.
kX86RegTypeMm
=
0x60
,
//! Xmm register.
kX86RegTypeXmm
=
0x70
,
//! Ymm register.
kX86RegTypeYmm
=
0x80
,
//! Zmm register.
kX86RegTypeZmm
=
0x90
,
//! Segment register.
kX86RegTypeSeg
=
0xF0
};
// ============================================================================
// [asmjit::kX86RegIndex]
// ============================================================================
//! X86/X64 register indexes.
//!
//! \note Register indexes have been reduced to only support general purpose
//! registers. There is no need to have enumerations with number suffix that
//! expands to the exactly same value as the suffix value itself.
ASMJIT_ENUM
(
kX86RegIndex
)
{
//! Index of Al/Ah/Ax/Eax/Rax registers.
kX86RegIndexAx
=
0
,
//! Index of Cl/Ch/Cx/Ecx/Rcx registers.
kX86RegIndexCx
=
1
,
//! Index of Dl/Dh/Dx/Edx/Rdx registers.
kX86RegIndexDx
=
2
,
//! Index of Bl/Bh/Bx/Ebx/Rbx registers.
kX86RegIndexBx
=
3
,
//! Index of Spl/Sp/Esp/Rsp registers.
kX86RegIndexSp
=
4
,
//! Index of Bpl/Bp/Ebp/Rbp registers.
kX86RegIndexBp
=
5
,
//! Index of Sil/Si/Esi/Rsi registers.
kX86RegIndexSi
=
6
,
//! Index of Dil/Di/Edi/Rdi registers.
kX86RegIndexDi
=
7
,
//! Index of R8b/R8w/R8d/R8 registers (64-bit only).
kX86RegIndexR8
=
8
,
//! Index of R9B/R9w/R9d/R9 registers (64-bit only).
kX86RegIndexR9
=
9
,
//! Index of R10B/R10w/R10D/R10 registers (64-bit only).
kX86RegIndexR10
=
10
,
//! Index of R11B/R11w/R11d/R11 registers (64-bit only).
kX86RegIndexR11
=
11
,
//! Index of R12B/R12w/R12d/R12 registers (64-bit only).
kX86RegIndexR12
=
12
,
//! Index of R13B/R13w/R13d/R13 registers (64-bit only).
kX86RegIndexR13
=
13
,
//! Index of R14B/R14w/R14d/R14 registers (64-bit only).
kX86RegIndexR14
=
14
,
//! Index of R15B/R15w/R15d/R15 registers (64-bit only).
kX86RegIndexR15
=
15
};
// ============================================================================
// [asmjit::kX86Seg]
// ============================================================================
//! X86/X64 segment codes.
ASMJIT_ENUM
(
kX86Seg
)
{
//! No/Default segment.
kX86SegDefault
=
0
,
//! Es segment.
kX86SegEs
=
1
,
//! Cs segment.
kX86SegCs
=
2
,
//! Ss segment.
kX86SegSs
=
3
,
//! Ds segment.
kX86SegDs
=
4
,
//! Fs segment.
kX86SegFs
=
5
,
//! Gs segment.
kX86SegGs
=
6
,
//! Count of X86 segment registers supported by AsmJit.
//!
//! \note X86 architecture has 6 segment registers - ES, CS, SS, DS, FS, GS.
//! X64 architecture lowers them down to just FS and GS. AsmJit supports 7
//! segment registers - all addressable in both X86 and X64 modes and one
//! extra called `kX86SegDefault`, which is AsmJit specific and means that there
//! is no segment register specified so the segment prefix will not be emitted.
kX86SegCount
=
7
};
// ============================================================================
// [asmjit::kX86MemVSib]
// ============================================================================
//! X86/X64 index register legacy and AVX2 (VSIB) support.
ASMJIT_ENUM
(
kX86MemVSib
)
{
//! Memory operand uses Gp or no index register.
kX86MemVSibGpz
=
0
,
//! Memory operand uses Xmm or no index register.
kX86MemVSibXmm
=
1
,
//! Memory operand uses Ymm or no index register.
kX86MemVSibYmm
=
2
};
// ============================================================================
// [asmjit::kX86MemFlags]
// ============================================================================
//! \internal
//!
//! X86/X64 specific memory flags.
ASMJIT_ENUM
(
kX86MemFlags
)
{
kX86MemSegBits
=
0x7
,
kX86MemSegIndex
=
0
,
kX86MemSegMask
=
kX86MemSegBits
<<
kX86MemSegIndex
,
kX86MemGpdBits
=
0x1
,
kX86MemGpdIndex
=
3
,
kX86MemGpdMask
=
kX86MemGpdBits
<<
kX86MemGpdIndex
,
kX86MemVSibBits
=
0x3
,
kX86MemVSibIndex
=
4
,
kX86MemVSibMask
=
kX86MemVSibBits
<<
kX86MemVSibIndex
,
kX86MemShiftBits
=
0x3
,
kX86MemShiftIndex
=
6
,
kX86MemShiftMask
=
kX86MemShiftBits
<<
kX86MemShiftIndex
};
// This is only defined by `x86operand_regs.cpp` when exporting registers.
#if !defined(ASMJIT_EXPORTS_X86OPERAND_REGS)
// ============================================================================
// [asmjit::X86RegCount]
// ============================================================================
//! \internal
//!
//! X86/X64 registers count (Gp, Fp, Mm, Xmm).
struct
X86RegCount
{
// --------------------------------------------------------------------------
// [Zero]
// --------------------------------------------------------------------------
ASMJIT_INLINE
void
reset
()
{
_packed
=
0
;
}
// --------------------------------------------------------------------------
// [Get]
// --------------------------------------------------------------------------
ASMJIT_INLINE
uint32_t
get
(
uint32_t
c
)
const
{
ASMJIT_ASSERT
(
c
<
kX86RegClassCount
);
return
_regs
[
c
];
}
ASMJIT_INLINE
uint32_t
getGp
()
const
{
return
_regs
[
kX86RegClassGp
];
}
ASMJIT_INLINE
uint32_t
getFp
()
const
{
return
_regs
[
kX86RegClassFp
];
}
ASMJIT_INLINE
uint32_t
getMm
()
const
{
return
_regs
[
kX86RegClassMm
];
}
ASMJIT_INLINE
uint32_t
getXyz
()
const
{
return
_regs
[
kX86RegClassXyz
];
}
// --------------------------------------------------------------------------
// [Set]
// --------------------------------------------------------------------------
ASMJIT_INLINE
void
set
(
uint32_t
c
,
uint32_t
n
)
{
ASMJIT_ASSERT
(
c
<
kX86RegClassCount
);
ASMJIT_ASSERT
(
n
<
0x100
);
_regs
[
c
]
=
static_cast
<
uint8_t
>
(
n
);
}
ASMJIT_INLINE
void
setGp
(
uint32_t
n
)
{
set
(
kX86RegClassGp
,
n
);
}
ASMJIT_INLINE
void
setFp
(
uint32_t
n
)
{
set
(
kX86RegClassFp
,
n
);
}
ASMJIT_INLINE
void
setMm
(
uint32_t
n
)
{
set
(
kX86RegClassMm
,
n
);
}
ASMJIT_INLINE
void
setXyz
(
uint32_t
n
)
{
set
(
kX86RegClassXyz
,
n
);
}
// --------------------------------------------------------------------------
// [Add]
// --------------------------------------------------------------------------
ASMJIT_INLINE
void
add
(
uint32_t
c
,
uint32_t
n
=
1
)
{
ASMJIT_ASSERT
(
c
<
kX86RegClassCount
);
ASMJIT_ASSERT
(
n
<
0x100
);
_regs
[
c
]
+=
static_cast
<
uint8_t
>
(
n
);
}
ASMJIT_INLINE
void
addGp
(
uint32_t
n
)
{
add
(
kX86RegClassGp
,
n
);
}
ASMJIT_INLINE
void
addFp
(
uint32_t
n
)
{
add
(
kX86RegClassFp
,
n
);
}
ASMJIT_INLINE
void
addMm
(
uint32_t
n
)
{
add
(
kX86RegClassMm
,
n
);
}
ASMJIT_INLINE
void
addXyz
(
uint32_t
n
)
{
add
(
kX86RegClassXyz
,
n
);
}
// --------------------------------------------------------------------------
// [Misc]
// --------------------------------------------------------------------------
ASMJIT_INLINE
void
makeIndex
(
const
X86RegCount
&
count
)
{
uint8_t
a
=
count
.
_regs
[
0
];
uint8_t
b
=
count
.
_regs
[
1
];
uint8_t
c
=
count
.
_regs
[
2
];
_regs
[
0
]
=
0
;
_regs
[
1
]
=
a
;
_regs
[
2
]
=
a
+
b
;
_regs
[
3
]
=
a
+
b
+
c
;
}
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
union
{
struct
{
uint8_t
_gp
;
uint8_t
_fp
;
uint8_t
_mm
;
uint8_t
_xy
;
};
uint8_t
_regs
[
4
];
uint32_t
_packed
;
};
};
// ============================================================================
// [asmjit::X86RegMask]
// ============================================================================
//! \internal
//!
//! X86/X64 registers mask (Gp, Fp, Mm, Xmm/Ymm/Zmm).
struct
X86RegMask
{
// --------------------------------------------------------------------------
// [Reset]
// --------------------------------------------------------------------------
ASMJIT_INLINE
void
reset
()
{
_packed
.
reset
();
}
// --------------------------------------------------------------------------
// [IsEmpty / Has]
// --------------------------------------------------------------------------
ASMJIT_INLINE
bool
isEmpty
()
const
{
return
_packed
.
isZero
();
}
ASMJIT_INLINE
bool
has
(
uint32_t
c
,
uint32_t
mask
=
0xFFFFFFFF
)
const
{
switch
(
c
)
{
case
kX86RegClassGp
:
return
(
static_cast
<
uint32_t
>
(
_gp
)
&
mask
)
!=
0
;
case
kX86RegClassFp
:
return
(
static_cast
<
uint32_t
>
(
_fp
)
&
mask
)
!=
0
;
case
kX86RegClassMm
:
return
(
static_cast
<
uint32_t
>
(
_mm
)
&
mask
)
!=
0
;
case
kX86RegClassXyz
:
return
(
static_cast
<
uint32_t
>
(
_xyz
)
&
mask
)
!=
0
;
}
ASMJIT_ASSERT
(
!
"Reached"
);
return
false
;
}
// --------------------------------------------------------------------------
// [Zero]
// --------------------------------------------------------------------------
ASMJIT_INLINE
void
zero
(
uint32_t
c
)
{
switch
(
c
)
{
case
kX86RegClassGp
:
_gp
=
0
;
break
;
case
kX86RegClassFp
:
_fp
=
0
;
break
;
case
kX86RegClassMm
:
_mm
=
0
;
break
;
case
kX86RegClassXyz
:
_xyz
=
0
;
break
;
}
}
// --------------------------------------------------------------------------
// [Get]
// --------------------------------------------------------------------------
ASMJIT_INLINE
uint32_t
get
(
uint32_t
c
)
const
{
switch
(
c
)
{
case
kX86RegClassGp
:
return
_gp
;
case
kX86RegClassFp
:
return
_fp
;
case
kX86RegClassMm
:
return
_mm
;
case
kX86RegClassXyz
:
return
_xyz
;
}
ASMJIT_ASSERT
(
!
"Reached"
);
return
0
;
}
// --------------------------------------------------------------------------
// [Set]
// --------------------------------------------------------------------------
ASMJIT_INLINE
void
set
(
uint32_t
c
,
uint32_t
mask
)
{
switch
(
c
)
{
case
kX86RegClassGp
:
_gp
=
static_cast
<
uint16_t
>
(
mask
);
break
;
case
kX86RegClassFp
:
_fp
=
static_cast
<
uint8_t
>
(
mask
);
break
;
case
kX86RegClassMm
:
_mm
=
static_cast
<
uint8_t
>
(
mask
);
break
;
case
kX86RegClassXyz
:
_xyz
=
static_cast
<
uint32_t
>
(
mask
);
break
;
}
}
ASMJIT_INLINE
void
set
(
const
X86RegMask
&
other
)
{
_packed
.
setUInt64
(
other
.
_packed
);
}
// --------------------------------------------------------------------------
// [Add]
// --------------------------------------------------------------------------
ASMJIT_INLINE
void
add
(
uint32_t
c
,
uint32_t
mask
)
{
switch
(
c
)
{
case
kX86RegClassGp
:
_gp
|=
static_cast
<
uint16_t
>
(
mask
);
break
;
case
kX86RegClassFp
:
_fp
|=
static_cast
<
uint8_t
>
(
mask
);
break
;
case
kX86RegClassMm
:
_mm
|=
static_cast
<
uint8_t
>
(
mask
);
break
;
case
kX86RegClassXyz
:
_xyz
|=
static_cast
<
uint32_t
>
(
mask
);
break
;
}
}
ASMJIT_INLINE
void
add
(
const
X86RegMask
&
other
)
{
_packed
.
or_
(
other
.
_packed
);
}
// --------------------------------------------------------------------------
// [Del]
// --------------------------------------------------------------------------
ASMJIT_INLINE
void
del
(
uint32_t
c
,
uint32_t
mask
)
{
switch
(
c
)
{
case
kX86RegClassGp
:
_gp
&=
~
static_cast
<
uint16_t
>
(
mask
);
break
;
case
kX86RegClassFp
:
_fp
&=
~
static_cast
<
uint8_t
>
(
mask
);
break
;
case
kX86RegClassMm
:
_mm
&=
~
static_cast
<
uint8_t
>
(
mask
);
break
;
case
kX86RegClassXyz
:
_xyz
&=
~
static_cast
<
uint32_t
>
(
mask
);
break
;
}
}
ASMJIT_INLINE
void
del
(
const
X86RegMask
&
other
)
{
_packed
.
del
(
other
.
_packed
);
}
// --------------------------------------------------------------------------
// [And]
// --------------------------------------------------------------------------
ASMJIT_INLINE
void
and_
(
uint32_t
c
,
uint32_t
mask
)
{
switch
(
c
)
{
case
kX86RegClassGp
:
_gp
&=
static_cast
<
uint16_t
>
(
mask
);
break
;
case
kX86RegClassFp
:
_fp
&=
static_cast
<
uint8_t
>
(
mask
);
break
;
case
kX86RegClassMm
:
_mm
&=
static_cast
<
uint8_t
>
(
mask
);
break
;
case
kX86RegClassXyz
:
_xyz
&=
static_cast
<
uint32_t
>
(
mask
);
break
;
}
}
ASMJIT_INLINE
void
and_
(
const
X86RegMask
&
other
)
{
_packed
.
and_
(
other
.
_packed
);
}
// --------------------------------------------------------------------------
// [Xor]
// --------------------------------------------------------------------------
ASMJIT_INLINE
void
xor_
(
uint32_t
c
,
uint32_t
mask
)
{
switch
(
c
)
{
case
kX86RegClassGp
:
_gp
^=
static_cast
<
uint16_t
>
(
mask
);
break
;
case
kX86RegClassFp
:
_fp
^=
static_cast
<
uint8_t
>
(
mask
);
break
;
case
kX86RegClassMm
:
_mm
^=
static_cast
<
uint8_t
>
(
mask
);
break
;
case
kX86RegClassXyz
:
_xyz
^=
static_cast
<
uint32_t
>
(
mask
);
break
;
}
}
ASMJIT_INLINE
void
xor_
(
const
X86RegMask
&
other
)
{
_packed
.
xor_
(
other
.
_packed
);
}
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
union
{
struct
{
//! Gp mask (16-bit).
uint16_t
_gp
;
//! Fp mask (8-bit).
uint8_t
_fp
;
//! Mm mask (8-bit).
uint8_t
_mm
;
//! Xmm/Ymm/Zmm mask (32-bit).
uint32_t
_xyz
;
};
//! All masks as 64-bit integer.
UInt64
_packed
;
};
};
// ============================================================================
// [asmjit::X86Reg]
// ============================================================================
//! Base class for all X86 registers.
struct
X86Reg
:
public
Reg
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! Create a dummy X86 register.
ASMJIT_INLINE
X86Reg
()
:
Reg
()
{}
//! Create a reference to `other` X86 register.
ASMJIT_INLINE
X86Reg
(
const
X86Reg
&
other
)
:
Reg
(
other
)
{}
//! Create a reference to `other` X86 register and change the index to `index`.
ASMJIT_INLINE
X86Reg
(
const
X86Reg
&
other
,
uint32_t
index
)
:
Reg
(
other
,
index
)
{}
//! Create a custom X86 register.
ASMJIT_INLINE
X86Reg
(
uint32_t
type
,
uint32_t
index
,
uint32_t
size
)
:
Reg
(
type
,
index
,
size
)
{}
//! Create non-initialized X86 register.
explicit
ASMJIT_INLINE
X86Reg
(
const
_NoInit
&
)
:
Reg
(
NoInit
)
{}
// --------------------------------------------------------------------------
// [X86Reg Specific]
// --------------------------------------------------------------------------
ASMJIT_REG_OP
(
X86Reg
)
//! Get whether the register is Gp register.
ASMJIT_INLINE
bool
isGp
()
const
{
return
_vreg
.
type
<=
kX86RegTypeGpq
;
}
//! Get whether the register is Gp byte (8-bit) register.
ASMJIT_INLINE
bool
isGpb
()
const
{
return
_vreg
.
type
<=
kX86RegTypeGpbHi
;
}
//! Get whether the register is Gp lo-byte (8-bit) register.
ASMJIT_INLINE
bool
isGpbLo
()
const
{
return
_vreg
.
type
==
kX86RegTypeGpbLo
;
}
//! Get whether the register is Gp hi-byte (8-bit) register.
ASMJIT_INLINE
bool
isGpbHi
()
const
{
return
_vreg
.
type
==
kX86RegTypeGpbHi
;
}
//! Get whether the register is Gp word (16-bit) register.
ASMJIT_INLINE
bool
isGpw
()
const
{
return
_vreg
.
type
==
kX86RegTypeGpw
;
}
//! Get whether the register is Gp dword (32-bit) register.
ASMJIT_INLINE
bool
isGpd
()
const
{
return
_vreg
.
type
==
kX86RegTypeGpd
;
}
//! Get whether the register is Gp qword (64-bit) register.
ASMJIT_INLINE
bool
isGpq
()
const
{
return
_vreg
.
type
==
kX86RegTypeGpq
;
}
//! Get whether the register is Fp register.
ASMJIT_INLINE
bool
isFp
()
const
{
return
_vreg
.
type
==
kX86RegTypeFp
;
}
//! Get whether the register is Mm (64-bit) register.
ASMJIT_INLINE
bool
isMm
()
const
{
return
_vreg
.
type
==
kX86RegTypeMm
;
}
//! Get whether the register is Xmm (128-bit) register.
ASMJIT_INLINE
bool
isXmm
()
const
{
return
_vreg
.
type
==
kX86RegTypeXmm
;
}
//! Get whether the register is Ymm (256-bit) register.
ASMJIT_INLINE
bool
isYmm
()
const
{
return
_vreg
.
type
==
kX86RegTypeYmm
;
}
//! Get whether the register is Zmm (512-bit) register.
ASMJIT_INLINE
bool
isZmm
()
const
{
return
_vreg
.
type
==
kX86RegTypeZmm
;
}
//! Get whether the register is a segment.
ASMJIT_INLINE
bool
isSeg
()
const
{
return
_vreg
.
type
==
kX86RegTypeSeg
;
}
// --------------------------------------------------------------------------
// [Statics]
// --------------------------------------------------------------------------
//! Get whether the `op` operand is Gpb-Lo or Gpb-Hi register.
static
ASMJIT_INLINE
bool
isGpbReg
(
const
Operand
&
op
)
{
const
uint32_t
mask
=
IntUtil
::
pack32_2x8_1x16
(
0xFF
,
0xFF
,
~
(
_kX86RegTypePatchedGpbHi
<<
8
)
&
0xFF00
);
return
(
op
.
_packed
[
0
].
u32
[
0
]
&
mask
)
==
IntUtil
::
pack32_2x8_1x16
(
kOperandTypeReg
,
1
,
0x0000
);
}
};
// ============================================================================
// [asmjit::X86GpReg]
// ============================================================================
//! X86/X64 Gpb/Gpw/Gpd/Gpq register.
struct
X86GpReg
:
public
X86Reg
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! Create a dummy Gp register.
ASMJIT_INLINE
X86GpReg
()
:
X86Reg
()
{}
//! Create a reference to `other` Gp register.
ASMJIT_INLINE
X86GpReg
(
const
X86GpReg
&
other
)
:
X86Reg
(
other
)
{}
//! Create a reference to `other` Gp register and change the index to `index`.
ASMJIT_INLINE
X86GpReg
(
const
X86GpReg
&
other
,
uint32_t
index
)
:
X86Reg
(
other
,
index
)
{}
//! Create a custom Gp register.
ASMJIT_INLINE
X86GpReg
(
uint32_t
type
,
uint32_t
index
,
uint32_t
size
)
:
X86Reg
(
type
,
index
,
size
)
{}
//! Create non-initialized Gp register.
explicit
ASMJIT_INLINE
X86GpReg
(
const
_NoInit
&
)
:
X86Reg
(
NoInit
)
{}
// --------------------------------------------------------------------------
// [X86GpReg Specific]
// --------------------------------------------------------------------------
ASMJIT_REG_OP
(
X86GpReg
)
};
// ============================================================================
// [asmjit::X86FpReg]
// ============================================================================
//! X86/X64 80-bit Fp register.
struct
X86FpReg
:
public
X86Reg
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! Create a dummy Fp register.
ASMJIT_INLINE
X86FpReg
()
:
X86Reg
()
{}
//! Create a reference to `other` Fp register.
ASMJIT_INLINE
X86FpReg
(
const
X86FpReg
&
other
)
:
X86Reg
(
other
)
{}
//! Create a reference to `other` Fp register and change the index to `index`.
ASMJIT_INLINE
X86FpReg
(
const
X86FpReg
&
other
,
uint32_t
index
)
:
X86Reg
(
other
,
index
)
{}
//! Create a custom Fp register.
ASMJIT_INLINE
X86FpReg
(
uint32_t
type
,
uint32_t
index
,
uint32_t
size
)
:
X86Reg
(
type
,
index
,
size
)
{}
//! Create non-initialized Fp register.
explicit
ASMJIT_INLINE
X86FpReg
(
const
_NoInit
&
)
:
X86Reg
(
NoInit
)
{}
// --------------------------------------------------------------------------
// [X86FpReg Specific]
// --------------------------------------------------------------------------
ASMJIT_REG_OP
(
X86FpReg
)
};
// ============================================================================
// [asmjit::X86MmReg]
// ============================================================================
//! X86/X64 64-bit Mm register.
struct
X86MmReg
:
public
X86Reg
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! Create a dummy Mm register.
ASMJIT_INLINE
X86MmReg
()
:
X86Reg
()
{}
//! Create a reference to `other` Mm register.
ASMJIT_INLINE
X86MmReg
(
const
X86MmReg
&
other
)
:
X86Reg
(
other
)
{}
//! Create a reference to `other` Mm register and change the index to `index`.
ASMJIT_INLINE
X86MmReg
(
const
X86MmReg
&
other
,
uint32_t
index
)
:
X86Reg
(
other
,
index
)
{}
//! Create a custom Mm register.
ASMJIT_INLINE
X86MmReg
(
uint32_t
type
,
uint32_t
index
,
uint32_t
size
)
:
X86Reg
(
type
,
index
,
size
)
{}
//! Create non-initialized Mm register.
explicit
ASMJIT_INLINE
X86MmReg
(
const
_NoInit
&
)
:
X86Reg
(
NoInit
)
{}
// --------------------------------------------------------------------------
// [X86MmReg Specific]
// --------------------------------------------------------------------------
ASMJIT_REG_OP
(
X86MmReg
)
};
// ============================================================================
// [asmjit::X86XmmReg]
// ============================================================================
//! X86/X64 128-bit Xmm register.
struct
X86XmmReg
:
public
X86Reg
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! Create a dummy Xmm register.
ASMJIT_INLINE
X86XmmReg
()
:
X86Reg
()
{}
//! Create a reference to `other` Xmm register.
ASMJIT_INLINE
X86XmmReg
(
const
X86XmmReg
&
other
)
:
X86Reg
(
other
)
{}
//! Create a reference to `other` Xmm register and change the index to `index`.
ASMJIT_INLINE
X86XmmReg
(
const
X86XmmReg
&
other
,
uint32_t
index
)
:
X86Reg
(
other
,
index
)
{}
//! Create a custom Xmm register.
ASMJIT_INLINE
X86XmmReg
(
uint32_t
type
,
uint32_t
index
,
uint32_t
size
)
:
X86Reg
(
type
,
index
,
size
)
{}
//! Create non-initialized Xmm register.
explicit
ASMJIT_INLINE
X86XmmReg
(
const
_NoInit
&
)
:
X86Reg
(
NoInit
)
{}
// --------------------------------------------------------------------------
// [X86XmmReg Specific]
// --------------------------------------------------------------------------
ASMJIT_REG_OP
(
X86XmmReg
)
};
// ============================================================================
// [asmjit::X86YmmReg]
// ============================================================================
//! X86/X64 256-bit Ymm register.
struct
X86YmmReg
:
public
X86Reg
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! Create a dummy Ymm register.
ASMJIT_INLINE
X86YmmReg
()
:
X86Reg
()
{}
//! Create a reference to `other` Xmm register.
ASMJIT_INLINE
X86YmmReg
(
const
X86YmmReg
&
other
)
:
X86Reg
(
other
)
{}
//! Create a reference to `other` Ymm register and change the index to `index`.
ASMJIT_INLINE
X86YmmReg
(
const
X86YmmReg
&
other
,
uint32_t
index
)
:
X86Reg
(
other
,
index
)
{}
//! Create a custom Ymm register.
ASMJIT_INLINE
X86YmmReg
(
uint32_t
type
,
uint32_t
index
,
uint32_t
size
)
:
X86Reg
(
type
,
index
,
size
)
{}
//! Create non-initialized Ymm register.
explicit
ASMJIT_INLINE
X86YmmReg
(
const
_NoInit
&
)
:
X86Reg
(
NoInit
)
{}
// --------------------------------------------------------------------------
// [X86YmmReg Specific]
// --------------------------------------------------------------------------
ASMJIT_REG_OP
(
X86YmmReg
)
};
// ============================================================================
// [asmjit::X86SegReg]
// ============================================================================
//! X86/X64 segment register.
struct
X86SegReg
:
public
X86Reg
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! Create a dummy segment register.
ASMJIT_INLINE
X86SegReg
()
:
X86Reg
()
{}
//! Create a reference to `other` segment register.
ASMJIT_INLINE
X86SegReg
(
const
X86SegReg
&
other
)
:
X86Reg
(
other
)
{}
//! Create a reference to `other` segment register and change the index to `index`.
ASMJIT_INLINE
X86SegReg
(
const
X86SegReg
&
other
,
uint32_t
index
)
:
X86Reg
(
other
,
index
)
{}
//! Create a custom segment register.
ASMJIT_INLINE
X86SegReg
(
uint32_t
type
,
uint32_t
index
,
uint32_t
size
)
:
X86Reg
(
type
,
index
,
size
)
{}
//! Create non-initialized segment register.
explicit
ASMJIT_INLINE
X86SegReg
(
const
_NoInit
&
)
:
X86Reg
(
NoInit
)
{}
// --------------------------------------------------------------------------
// [X86SegReg Specific]
// --------------------------------------------------------------------------
ASMJIT_REG_OP
(
X86SegReg
)
};
// ============================================================================
// [asmjit::X86Mem]
// ============================================================================
//! X86 memory operand.
struct
X86Mem
:
public
BaseMem
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
ASMJIT_INLINE
X86Mem
()
:
BaseMem
(
NoInit
)
{
reset
();
}
ASMJIT_INLINE
X86Mem
(
const
Label
&
label
,
int32_t
disp
,
uint32_t
size
=
0
)
:
BaseMem
(
NoInit
)
{
_init_packed_op_sz_b0_b1_id
(
kOperandTypeMem
,
size
,
kMemTypeLabel
,
0
,
label
.
_base
.
id
);
_init_packed_d2_d3
(
kInvalidValue
,
disp
);
}
ASMJIT_INLINE
X86Mem
(
const
Label
&
label
,
const
X86GpReg
&
index
,
uint32_t
shift
,
int32_t
disp
,
uint32_t
size
=
0
)
:
BaseMem
(
NoInit
)
{
ASMJIT_ASSERT
(
shift
<=
3
);
_init_packed_op_sz_b0_b1_id
(
kOperandTypeMem
,
size
,
kMemTypeLabel
,
(
kX86MemVSibGpz
<<
kX86MemVSibIndex
)
+
(
shift
<<
kX86MemShiftIndex
),
label
.
getId
());
_vmem
.
index
=
index
.
getRegIndex
();
_vmem
.
displacement
=
disp
;
}
ASMJIT_INLINE
X86Mem
(
const
X86GpReg
&
base
,
int32_t
disp
,
uint32_t
size
=
0
)
:
BaseMem
(
NoInit
)
{
_init_packed_op_sz_b0_b1_id
(
kOperandTypeMem
,
size
,
kMemTypeBaseIndex
,
_getGpdFlags
(
base
)
+
(
kX86MemVSibGpz
<<
kX86MemVSibIndex
),
base
.
getRegIndex
());
_init_packed_d2_d3
(
kInvalidValue
,
disp
);
}
ASMJIT_INLINE
X86Mem
(
const
X86GpReg
&
base
,
const
X86GpReg
&
index
,
uint32_t
shift
,
int32_t
disp
,
uint32_t
size
=
0
)
:
BaseMem
(
NoInit
)
{
ASMJIT_ASSERT
(
shift
<=
3
);
_init_packed_op_sz_b0_b1_id
(
kOperandTypeMem
,
size
,
kMemTypeBaseIndex
,
_getGpdFlags
(
base
)
+
(
shift
<<
kX86MemShiftIndex
),
base
.
getRegIndex
());
_vmem
.
index
=
index
.
getRegIndex
();
_vmem
.
displacement
=
disp
;
}
ASMJIT_INLINE
X86Mem
(
const
X86GpReg
&
base
,
const
X86XmmReg
&
index
,
uint32_t
shift
,
int32_t
disp
,
uint32_t
size
=
0
)
:
BaseMem
(
NoInit
)
{
ASMJIT_ASSERT
(
shift
<=
3
);
_init_packed_op_sz_b0_b1_id
(
kOperandTypeMem
,
size
,
kMemTypeBaseIndex
,
_getGpdFlags
(
base
)
+
(
kX86MemVSibXmm
<<
kX86MemVSibIndex
)
+
(
shift
<<
kX86MemShiftIndex
),
base
.
getRegIndex
());
_vmem
.
index
=
index
.
getRegIndex
();
_vmem
.
displacement
=
disp
;
}
ASMJIT_INLINE
X86Mem
(
const
X86GpReg
&
base
,
const
X86YmmReg
&
index
,
uint32_t
shift
,
int32_t
disp
,
uint32_t
size
=
0
)
:
BaseMem
(
NoInit
)
{
ASMJIT_ASSERT
(
shift
<=
3
);
_init_packed_op_sz_b0_b1_id
(
kOperandTypeMem
,
size
,
kMemTypeBaseIndex
,
_getGpdFlags
(
base
)
+
(
kX86MemVSibYmm
<<
kX86MemVSibIndex
)
+
(
shift
<<
kX86MemShiftIndex
),
base
.
getRegIndex
());
_vmem
.
index
=
index
.
getRegIndex
();
_vmem
.
displacement
=
disp
;
}
#if !defined(ASMJIT_DISABLE_COMPILER)
ASMJIT_INLINE
X86Mem
(
const
Label
&
label
,
const
X86GpVar
&
index
,
uint32_t
shift
,
int32_t
disp
,
uint32_t
size
=
0
)
:
BaseMem
(
NoInit
)
{
ASMJIT_ASSERT
(
shift
<=
3
);
_init_packed_op_sz_b0_b1_id
(
kOperandTypeMem
,
size
,
kMemTypeLabel
,
(
kX86MemVSibGpz
<<
kX86MemVSibIndex
)
+
(
shift
<<
kX86MemShiftIndex
),
label
.
getId
());
_vmem
.
index
=
_OP_ID
(
index
);
_vmem
.
displacement
=
disp
;
}
ASMJIT_INLINE
X86Mem
(
const
X86GpVar
&
base
,
int32_t
disp
,
uint32_t
size
=
0
)
:
BaseMem
(
NoInit
)
{
_init_packed_op_sz_b0_b1_id
(
kOperandTypeMem
,
size
,
kMemTypeBaseIndex
,
_getGpdFlags
(
reinterpret_cast
<
const
Var
&>
(
base
))
+
(
kX86MemVSibGpz
<<
kX86MemVSibIndex
),
_OP_ID
(
base
));
_init_packed_d2_d3
(
kInvalidValue
,
disp
);
}
ASMJIT_INLINE
X86Mem
(
const
X86GpVar
&
base
,
const
X86GpVar
&
index
,
uint32_t
shift
,
int32_t
disp
,
uint32_t
size
=
0
)
:
BaseMem
(
NoInit
)
{
ASMJIT_ASSERT
(
shift
<=
3
);
_init_packed_op_sz_b0_b1_id
(
kOperandTypeMem
,
size
,
kMemTypeBaseIndex
,
_getGpdFlags
(
reinterpret_cast
<
const
Var
&>
(
base
))
+
(
shift
<<
kX86MemShiftIndex
),
_OP_ID
(
base
));
_vmem
.
index
=
_OP_ID
(
index
);
_vmem
.
displacement
=
disp
;
}
ASMJIT_INLINE
X86Mem
(
const
X86GpVar
&
base
,
const
X86XmmVar
&
index
,
uint32_t
shift
,
int32_t
disp
,
uint32_t
size
=
0
)
:
BaseMem
(
NoInit
)
{
ASMJIT_ASSERT
(
shift
<=
3
);
_init_packed_op_sz_b0_b1_id
(
kOperandTypeMem
,
size
,
kMemTypeBaseIndex
,
_getGpdFlags
(
reinterpret_cast
<
const
Var
&>
(
base
))
+
(
kX86MemVSibXmm
<<
kX86MemVSibIndex
)
+
(
shift
<<
kX86MemShiftIndex
),
_OP_ID
(
base
));
_vmem
.
index
=
_OP_ID
(
index
);
_vmem
.
displacement
=
disp
;
}
ASMJIT_INLINE
X86Mem
(
const
X86GpVar
&
base
,
const
X86YmmVar
&
index
,
uint32_t
shift
,
int32_t
disp
,
uint32_t
size
=
0
)
:
BaseMem
(
NoInit
)
{
ASMJIT_ASSERT
(
shift
<=
3
);
_init_packed_op_sz_b0_b1_id
(
kOperandTypeMem
,
size
,
kMemTypeBaseIndex
,
_getGpdFlags
(
reinterpret_cast
<
const
Var
&>
(
base
))
+
(
kX86MemVSibYmm
<<
kX86MemVSibIndex
)
+
(
shift
<<
kX86MemShiftIndex
),
_OP_ID
(
base
));
_vmem
.
index
=
_OP_ID
(
index
);
_vmem
.
displacement
=
disp
;
}
ASMJIT_INLINE
X86Mem
(
const
_Init
&
,
uint32_t
memType
,
const
X86Var
&
base
,
int32_t
disp
,
uint32_t
size
)
:
BaseMem
(
NoInit
)
{
_init_packed_op_sz_b0_b1_id
(
kOperandTypeMem
,
size
,
memType
,
0
,
_OP_ID
(
base
));
_vmem
.
index
=
kInvalidValue
;
_vmem
.
displacement
=
disp
;
}
ASMJIT_INLINE
X86Mem
(
const
_Init
&
,
uint32_t
memType
,
const
X86Var
&
base
,
const
X86GpVar
&
index
,
uint32_t
shift
,
int32_t
disp
,
uint32_t
size
)
:
BaseMem
(
NoInit
)
{
ASMJIT_ASSERT
(
shift
<=
3
);
_init_packed_op_sz_b0_b1_id
(
kOperandTypeMem
,
size
,
memType
,
shift
<<
kX86MemShiftIndex
,
_OP_ID
(
base
));
_vmem
.
index
=
_OP_ID
(
index
);
_vmem
.
displacement
=
disp
;
}
#endif // !ASMJIT_DISABLE_COMPILER
ASMJIT_INLINE
X86Mem
(
const
X86Mem
&
other
)
:
BaseMem
(
other
)
{}
explicit
ASMJIT_INLINE
X86Mem
(
const
_NoInit
&
)
:
BaseMem
(
NoInit
)
{}
// --------------------------------------------------------------------------
// [X86Mem Specific]
// --------------------------------------------------------------------------
//! Clone X86Mem operand.
ASMJIT_INLINE
X86Mem
clone
()
const
{
return
X86Mem
(
*
this
);
}
//! Reset X86Mem operand.
ASMJIT_INLINE
void
reset
()
{
_init_packed_op_sz_b0_b1_id
(
kOperandTypeMem
,
0
,
kMemTypeBaseIndex
,
0
,
kInvalidValue
);
_init_packed_d2_d3
(
kInvalidValue
,
0
);
}
//! \internal
ASMJIT_INLINE
void
_init
(
uint32_t
memType
,
uint32_t
base
,
int32_t
disp
,
uint32_t
size
)
{
_init_packed_op_sz_b0_b1_id
(
kOperandTypeMem
,
size
,
memType
,
0
,
base
);
_vmem
.
index
=
kInvalidValue
;
_vmem
.
displacement
=
disp
;
}
// --------------------------------------------------------------------------
// [Segment]
// --------------------------------------------------------------------------
//! Get whether the memory operand has segment override prefix.
ASMJIT_INLINE
bool
hasSegment
()
const
{
return
(
_vmem
.
flags
&
kX86MemSegMask
)
!=
(
kX86SegDefault
<<
kX86MemSegIndex
);
}
//! Get memory operand segment, see `kX86Seg`.
ASMJIT_INLINE
uint32_t
getSegment
()
const
{
return
(
static_cast
<
uint32_t
>
(
_vmem
.
flags
)
>>
kX86MemSegIndex
)
&
kX86MemSegBits
;
}
//! Set memory operand segment, see `kX86Seg`.
ASMJIT_INLINE
X86Mem
&
setSegment
(
uint32_t
segIndex
)
{
_vmem
.
flags
=
static_cast
<
uint8_t
>
(
(
static_cast
<
uint32_t
>
(
_vmem
.
flags
)
&
kX86MemSegMask
)
+
(
segIndex
<<
kX86MemSegIndex
));
return
*
this
;
}
//! Set memory operand segment, see `kX86Seg`.
ASMJIT_INLINE
X86Mem
&
setSegment
(
const
X86SegReg
&
seg
)
{
return
setSegment
(
seg
.
getRegIndex
());
}
// --------------------------------------------------------------------------
// [Gpd]
// --------------------------------------------------------------------------
//! Get whether the memory operand has 32-bit GP base.
ASMJIT_INLINE
bool
hasGpdBase
()
const
{
return
(
_packed
[
0
].
u32
[
0
]
&
IntUtil
::
pack32_4x8
(
0x00
,
0x00
,
0x00
,
kX86MemGpdMask
))
!=
0
;
}
//! Set whether the memory operand has 32-bit GP base.
ASMJIT_INLINE
X86Mem
&
setGpdBase
()
{
_packed
[
0
].
u32
[
0
]
|=
IntUtil
::
pack32_4x8
(
0x00
,
0x00
,
0x00
,
kX86MemGpdMask
);
return
*
this
;
}
//! Set whether the memory operand has 32-bit GP base to `b`.
ASMJIT_INLINE
X86Mem
&
setGpdBase
(
uint32_t
b
)
{
_packed
[
0
].
u32
[
0
]
&=~
IntUtil
::
pack32_4x8
(
0x00
,
0x00
,
0x00
,
kX86MemGpdMask
);
_packed
[
0
].
u32
[
0
]
|=
IntUtil
::
pack32_4x8
(
0x00
,
0x00
,
0x00
,
b
<<
kX86MemGpdIndex
);
return
*
this
;
}
// --------------------------------------------------------------------------
// [VSib]
// --------------------------------------------------------------------------
//! Get SIB type.
ASMJIT_INLINE
uint32_t
getVSib
()
const
{
return
(
static_cast
<
uint32_t
>
(
_vmem
.
flags
)
>>
kX86MemVSibIndex
)
&
kX86MemVSibBits
;
}
//! Set SIB type.
ASMJIT_INLINE
X86Mem
&
_setVSib
(
uint32_t
vsib
)
{
_packed
[
0
].
u32
[
0
]
&=~
IntUtil
::
pack32_4x8
(
0x00
,
0x00
,
0x00
,
kX86MemVSibMask
);
_packed
[
0
].
u32
[
0
]
|=
IntUtil
::
pack32_4x8
(
0x00
,
0x00
,
0x00
,
vsib
<<
kX86MemVSibIndex
);
return
*
this
;
}
// --------------------------------------------------------------------------
// [Size]
// --------------------------------------------------------------------------
//! Set memory operand size.
ASMJIT_INLINE
X86Mem
&
setSize
(
uint32_t
size
)
{
_vmem
.
size
=
static_cast
<
uint8_t
>
(
size
);
return
*
this
;
}
// --------------------------------------------------------------------------
// [Base]
// --------------------------------------------------------------------------
//! Get whether the memory operand has base register.
ASMJIT_INLINE
bool
hasBase
()
const
{
return
_vmem
.
base
!=
kInvalidValue
;
}
//! Get memory operand base register code, variable id, or `kInvalidValue`.
ASMJIT_INLINE
uint32_t
getBase
()
const
{
return
_vmem
.
base
;
}
//! Set memory operand base register code, variable id, or `kInvalidValue`.
ASMJIT_INLINE
X86Mem
&
setBase
(
uint32_t
base
)
{
_vmem
.
base
=
base
;
return
*
this
;
}
// --------------------------------------------------------------------------
// [Index]
// --------------------------------------------------------------------------
//! Get whether the memory operand has index.
ASMJIT_INLINE
bool
hasIndex
()
const
{
return
_vmem
.
index
!=
kInvalidValue
;
}
//! Get memory operand index register code, variable id, or `kInvalidValue`.
ASMJIT_INLINE
uint32_t
getIndex
()
const
{
return
_vmem
.
index
;
}
//! Set memory operand index register code, variable id, or `kInvalidValue`.
ASMJIT_INLINE
X86Mem
&
setIndex
(
uint32_t
index
)
{
_vmem
.
index
=
index
;
return
*
this
;
}
//! Set memory index.
ASMJIT_INLINE
X86Mem
&
setIndex
(
const
X86GpReg
&
index
)
{
_vmem
.
index
=
index
.
getRegIndex
();
return
_setVSib
(
kX86MemVSibGpz
);
}
//! Set memory index.
ASMJIT_INLINE
X86Mem
&
setIndex
(
const
X86GpReg
&
index
,
uint32_t
shift
)
{
_vmem
.
index
=
index
.
getRegIndex
();
return
_setVSib
(
kX86MemVSibGpz
).
setShift
(
shift
);
}
//! Set memory index.
ASMJIT_INLINE
X86Mem
&
setIndex
(
const
X86XmmReg
&
index
)
{
_vmem
.
index
=
index
.
getRegIndex
();
return
_setVSib
(
kX86MemVSibXmm
);
}
//! Set memory index.
ASMJIT_INLINE
X86Mem
&
setIndex
(
const
X86XmmReg
&
index
,
uint32_t
shift
)
{
_vmem
.
index
=
index
.
getRegIndex
();
return
_setVSib
(
kX86MemVSibXmm
).
setShift
(
shift
);
}
//! Set memory index.
ASMJIT_INLINE
X86Mem
&
setIndex
(
const
X86YmmReg
&
index
)
{
_vmem
.
index
=
index
.
getRegIndex
();
return
_setVSib
(
kX86MemVSibYmm
);
}
//! Set memory index.
ASMJIT_INLINE
X86Mem
&
setIndex
(
const
X86YmmReg
&
index
,
uint32_t
shift
)
{
_vmem
.
index
=
index
.
getRegIndex
();
return
_setVSib
(
kX86MemVSibYmm
).
setShift
(
shift
);
}
#if !defined(ASMJIT_DISABLE_COMPILER)
//! Set memory index.
ASMJIT_INLINE
X86Mem
&
setIndex
(
const
X86GpVar
&
index
)
{
_vmem
.
index
=
_OP_ID
(
index
);
return
_setVSib
(
kX86MemVSibGpz
);
}
//! Set memory index.
ASMJIT_INLINE
X86Mem
&
setIndex
(
const
X86GpVar
&
index
,
uint32_t
shift
)
{
_vmem
.
index
=
_OP_ID
(
index
);
return
_setVSib
(
kX86MemVSibGpz
).
setShift
(
shift
);
}
//! Set memory index.
ASMJIT_INLINE
X86Mem
&
setIndex
(
const
X86XmmVar
&
index
)
{
_vmem
.
index
=
_OP_ID
(
index
);
return
_setVSib
(
kX86MemVSibXmm
);
}
//! Set memory index.
ASMJIT_INLINE
X86Mem
&
setIndex
(
const
X86XmmVar
&
index
,
uint32_t
shift
)
{
_vmem
.
index
=
_OP_ID
(
index
);
return
_setVSib
(
kX86MemVSibXmm
).
setShift
(
shift
);
}
//! Set memory index.
ASMJIT_INLINE
X86Mem
&
setIndex
(
const
X86YmmVar
&
index
)
{
_vmem
.
index
=
_OP_ID
(
index
);
return
_setVSib
(
kX86MemVSibYmm
);
}
//! Set memory index.
ASMJIT_INLINE
X86Mem
&
setIndex
(
const
X86YmmVar
&
index
,
uint32_t
shift
)
{
_vmem
.
index
=
_OP_ID
(
index
);
return
_setVSib
(
kX86MemVSibYmm
).
setShift
(
shift
);
}
#endif // !ASMJIT_DISABLE_COMPILER
//! Reset memory index.
ASMJIT_INLINE
X86Mem
&
resetIndex
()
{
_vmem
.
index
=
kInvalidValue
;
return
_setVSib
(
kX86MemVSibGpz
);
}
// --------------------------------------------------------------------------
// [Misc]
// --------------------------------------------------------------------------
//! Get whether the memory operand has base and index register.
ASMJIT_INLINE
bool
hasBaseOrIndex
()
const
{
return
_vmem
.
base
!=
kInvalidValue
||
_vmem
.
index
!=
kInvalidValue
;
}
//! Get whether the memory operand has base and index register.
ASMJIT_INLINE
bool
hasBaseAndIndex
()
const
{
return
_vmem
.
base
!=
kInvalidValue
&&
_vmem
.
index
!=
kInvalidValue
;
}
// --------------------------------------------------------------------------
// [Shift]
// --------------------------------------------------------------------------
//! Get whether the memory operand has shift used.
ASMJIT_INLINE
bool
hasShift
()
const
{
return
(
_vmem
.
flags
&
kX86MemShiftMask
)
!=
0
;
}
//! Get memory operand index scale (0, 1, 2 or 3).
ASMJIT_INLINE
uint32_t
getShift
()
const
{
return
_vmem
.
flags
>>
kX86MemShiftIndex
;
}
//! Set memory operand index scale (0, 1, 2 or 3).
ASMJIT_INLINE
X86Mem
&
setShift
(
uint32_t
shift
)
{
_packed
[
0
].
u32
[
0
]
&=~
IntUtil
::
pack32_4x8
(
0x00
,
0x00
,
0x00
,
kX86MemShiftMask
);
_packed
[
0
].
u32
[
0
]
|=
IntUtil
::
pack32_4x8
(
0x00
,
0x00
,
0x00
,
shift
<<
kX86MemShiftIndex
);
return
*
this
;
}
// --------------------------------------------------------------------------
// [Displacement]
// --------------------------------------------------------------------------
//! Get memory operand relative displacement.
ASMJIT_INLINE
int32_t
getDisplacement
()
const
{
return
_vmem
.
displacement
;
}
//! Set memory operand relative displacement.
ASMJIT_INLINE
X86Mem
&
setDisplacement
(
int32_t
disp
)
{
_vmem
.
displacement
=
disp
;
return
*
this
;
}
//! Reset memory operand relative displacement.
ASMJIT_INLINE
X86Mem
&
resetDisplacement
(
int32_t
disp
)
{
_vmem
.
displacement
=
0
;
return
*
this
;
}
//! Adjust memory operand relative displacement by `disp`.
ASMJIT_INLINE
X86Mem
&
adjust
(
int32_t
disp
)
{
_vmem
.
displacement
+=
disp
;
return
*
this
;
}
//! Get new memory operand adjusted by `disp`.
ASMJIT_INLINE
X86Mem
adjusted
(
int32_t
disp
)
const
{
X86Mem
result
(
*
this
);
result
.
adjust
(
disp
);
return
result
;
}
// --------------------------------------------------------------------------
// [Operator Overload]
// --------------------------------------------------------------------------
ASMJIT_INLINE
X86Mem
&
operator
=
(
const
X86Mem
&
other
)
{
_copy
(
other
);
return
*
this
;
}
ASMJIT_INLINE
bool
operator
==
(
const
X86Mem
&
other
)
const
{
return
(
_packed
[
0
]
==
other
.
_packed
[
0
])
&
(
_packed
[
1
]
==
other
.
_packed
[
1
])
;
}
ASMJIT_INLINE
bool
operator
!=
(
const
X86Mem
&
other
)
const
{
return
!
(
*
this
==
other
);
}
// --------------------------------------------------------------------------
// [Static]
// --------------------------------------------------------------------------
static
ASMJIT_INLINE
uint32_t
_getGpdFlags
(
const
Operand
&
base
)
{
return
(
base
.
_vreg
.
size
&
0x4
)
<<
(
kX86MemGpdIndex
-
2
);
}
};
#endif // !ASMJIT_EXPORTS_X86OPERAND_REGS
// ============================================================================
// [asmjit::x86]
// ============================================================================
namespace
x86
{
// ============================================================================
// [asmjit::x86 - Reg]
// ============================================================================
//! No Gp register, can be used only within `X86Mem` operand.
ASMJIT_VAR
const
X86GpReg
noGpReg
;
ASMJIT_VAR
const
X86GpReg
al
;
//!< 8-bit Gpb-lo register.
ASMJIT_VAR
const
X86GpReg
cl
;
//!< 8-bit Gpb-lo register.
ASMJIT_VAR
const
X86GpReg
dl
;
//!< 8-bit Gpb-lo register.
ASMJIT_VAR
const
X86GpReg
bl
;
//!< 8-bit Gpb-lo register.
ASMJIT_VAR
const
X86GpReg
spl
;
//!< 8-bit Gpb-lo register (X64).
ASMJIT_VAR
const
X86GpReg
bpl
;
//!< 8-bit Gpb-lo register (X64).
ASMJIT_VAR
const
X86GpReg
sil
;
//!< 8-bit Gpb-lo register (X64).
ASMJIT_VAR
const
X86GpReg
dil
;
//!< 8-bit Gpb-lo register (X64).
ASMJIT_VAR
const
X86GpReg
r8b
;
//!< 8-bit Gpb-lo register (X64).
ASMJIT_VAR
const
X86GpReg
r9b
;
//!< 8-bit Gpb-lo register (X64).
ASMJIT_VAR
const
X86GpReg
r10b
;
//!< 8-bit Gpb-lo register (X64).
ASMJIT_VAR
const
X86GpReg
r11b
;
//!< 8-bit Gpb-lo register (X64).
ASMJIT_VAR
const
X86GpReg
r12b
;
//!< 8-bit Gpb-lo register (X64).
ASMJIT_VAR
const
X86GpReg
r13b
;
//!< 8-bit Gpb-lo register (X64).
ASMJIT_VAR
const
X86GpReg
r14b
;
//!< 8-bit Gpb-lo register (X64).
ASMJIT_VAR
const
X86GpReg
r15b
;
//!< 8-bit Gpb-lo register (X64).
ASMJIT_VAR
const
X86GpReg
ah
;
//!< 8-bit Gpb-hi register.
ASMJIT_VAR
const
X86GpReg
ch
;
//!< 8-bit Gpb-hi register.
ASMJIT_VAR
const
X86GpReg
dh
;
//!< 8-bit Gpb-hi register.
ASMJIT_VAR
const
X86GpReg
bh
;
//!< 8-bit Gpb-hi register.
ASMJIT_VAR
const
X86GpReg
ax
;
//!< 16-bit Gpw register.
ASMJIT_VAR
const
X86GpReg
cx
;
//!< 16-bit Gpw register.
ASMJIT_VAR
const
X86GpReg
dx
;
//!< 16-bit Gpw register.
ASMJIT_VAR
const
X86GpReg
bx
;
//!< 16-bit Gpw register.
ASMJIT_VAR
const
X86GpReg
sp
;
//!< 16-bit Gpw register.
ASMJIT_VAR
const
X86GpReg
bp
;
//!< 16-bit Gpw register.
ASMJIT_VAR
const
X86GpReg
si
;
//!< 16-bit Gpw register.
ASMJIT_VAR
const
X86GpReg
di
;
//!< 16-bit Gpw register.
ASMJIT_VAR
const
X86GpReg
r8w
;
//!< 16-bit Gpw register (X64).
ASMJIT_VAR
const
X86GpReg
r9w
;
//!< 16-bit Gpw register (X64).
ASMJIT_VAR
const
X86GpReg
r10w
;
//!< 16-bit Gpw register (X64).
ASMJIT_VAR
const
X86GpReg
r11w
;
//!< 16-bit Gpw register (X64).
ASMJIT_VAR
const
X86GpReg
r12w
;
//!< 16-bit Gpw register (X64).
ASMJIT_VAR
const
X86GpReg
r13w
;
//!< 16-bit Gpw register (X64).
ASMJIT_VAR
const
X86GpReg
r14w
;
//!< 16-bit Gpw register (X64).
ASMJIT_VAR
const
X86GpReg
r15w
;
//!< 16-bit Gpw register (X64).
ASMJIT_VAR
const
X86GpReg
eax
;
//!< 32-bit Gpd register.
ASMJIT_VAR
const
X86GpReg
ecx
;
//!< 32-bit Gpd register.
ASMJIT_VAR
const
X86GpReg
edx
;
//!< 32-bit Gpd register.
ASMJIT_VAR
const
X86GpReg
ebx
;
//!< 32-bit Gpd register.
ASMJIT_VAR
const
X86GpReg
esp
;
//!< 32-bit Gpd register.
ASMJIT_VAR
const
X86GpReg
ebp
;
//!< 32-bit Gpd register.
ASMJIT_VAR
const
X86GpReg
esi
;
//!< 32-bit Gpd register.
ASMJIT_VAR
const
X86GpReg
edi
;
//!< 32-bit Gpd register.
ASMJIT_VAR
const
X86GpReg
r8d
;
//!< 32-bit Gpd register (X64).
ASMJIT_VAR
const
X86GpReg
r9d
;
//!< 32-bit Gpd register (X64).
ASMJIT_VAR
const
X86GpReg
r10d
;
//!< 32-bit Gpd register (X64).
ASMJIT_VAR
const
X86GpReg
r11d
;
//!< 32-bit Gpd register (X64).
ASMJIT_VAR
const
X86GpReg
r12d
;
//!< 32-bit Gpd register (X64).
ASMJIT_VAR
const
X86GpReg
r13d
;
//!< 32-bit Gpd register (X64).
ASMJIT_VAR
const
X86GpReg
r14d
;
//!< 32-bit Gpd register (X64).
ASMJIT_VAR
const
X86GpReg
r15d
;
//!< 32-bit Gpd register (X64).
ASMJIT_VAR
const
X86GpReg
rax
;
//!< 64-bit Gpq register (X64).
ASMJIT_VAR
const
X86GpReg
rcx
;
//!< 64-bit Gpq register (X64)
ASMJIT_VAR
const
X86GpReg
rdx
;
//!< 64-bit Gpq register (X64)
ASMJIT_VAR
const
X86GpReg
rbx
;
//!< 64-bit Gpq register (X64)
ASMJIT_VAR
const
X86GpReg
rsp
;
//!< 64-bit Gpq register (X64)
ASMJIT_VAR
const
X86GpReg
rbp
;
//!< 64-bit Gpq register (X64)
ASMJIT_VAR
const
X86GpReg
rsi
;
//!< 64-bit Gpq register (X64)
ASMJIT_VAR
const
X86GpReg
rdi
;
//!< 64-bit Gpq register (X64)
ASMJIT_VAR
const
X86GpReg
r8
;
//!< 64-bit Gpq register (X64)
ASMJIT_VAR
const
X86GpReg
r9
;
//!< 64-bit Gpq register (X64)
ASMJIT_VAR
const
X86GpReg
r10
;
//!< 64-bit Gpq register (X64)
ASMJIT_VAR
const
X86GpReg
r11
;
//!< 64-bit Gpq register (X64)
ASMJIT_VAR
const
X86GpReg
r12
;
//!< 64-bit Gpq register (X64)
ASMJIT_VAR
const
X86GpReg
r13
;
//!< 64-bit Gpq register (X64)
ASMJIT_VAR
const
X86GpReg
r14
;
//!< 64-bit Gpq register (X64)
ASMJIT_VAR
const
X86GpReg
r15
;
//!< 64-bit Gpq register (X64)
ASMJIT_VAR
const
X86FpReg
fp0
;
//!< 80-bit Fp register.
ASMJIT_VAR
const
X86FpReg
fp1
;
//!< 80-bit Fp register.
ASMJIT_VAR
const
X86FpReg
fp2
;
//!< 80-bit Fp register.
ASMJIT_VAR
const
X86FpReg
fp3
;
//!< 80-bit Fp register.
ASMJIT_VAR
const
X86FpReg
fp4
;
//!< 80-bit Fp register.
ASMJIT_VAR
const
X86FpReg
fp5
;
//!< 80-bit Fp register.
ASMJIT_VAR
const
X86FpReg
fp6
;
//!< 80-bit Fp register.
ASMJIT_VAR
const
X86FpReg
fp7
;
//!< 80-bit Fp register.
ASMJIT_VAR
const
X86MmReg
mm0
;
//!< 64-bit Mm register.
ASMJIT_VAR
const
X86MmReg
mm1
;
//!< 64-bit Mm register.
ASMJIT_VAR
const
X86MmReg
mm2
;
//!< 64-bit Mm register.
ASMJIT_VAR
const
X86MmReg
mm3
;
//!< 64-bit Mm register.
ASMJIT_VAR
const
X86MmReg
mm4
;
//!< 64-bit Mm register.
ASMJIT_VAR
const
X86MmReg
mm5
;
//!< 64-bit Mm register.
ASMJIT_VAR
const
X86MmReg
mm6
;
//!< 64-bit Mm register.
ASMJIT_VAR
const
X86MmReg
mm7
;
//!< 64-bit Mm register.
ASMJIT_VAR
const
X86XmmReg
xmm0
;
//!< 128-bit Xmm register.
ASMJIT_VAR
const
X86XmmReg
xmm1
;
//!< 128-bit Xmm register.
ASMJIT_VAR
const
X86XmmReg
xmm2
;
//!< 128-bit Xmm register.
ASMJIT_VAR
const
X86XmmReg
xmm3
;
//!< 128-bit Xmm register.
ASMJIT_VAR
const
X86XmmReg
xmm4
;
//!< 128-bit Xmm register.
ASMJIT_VAR
const
X86XmmReg
xmm5
;
//!< 128-bit Xmm register.
ASMJIT_VAR
const
X86XmmReg
xmm6
;
//!< 128-bit Xmm register.
ASMJIT_VAR
const
X86XmmReg
xmm7
;
//!< 128-bit Xmm register.
ASMJIT_VAR
const
X86XmmReg
xmm8
;
//!< 128-bit Xmm register (X64).
ASMJIT_VAR
const
X86XmmReg
xmm9
;
//!< 128-bit Xmm register (X64).
ASMJIT_VAR
const
X86XmmReg
xmm10
;
//!< 128-bit Xmm register (X64).
ASMJIT_VAR
const
X86XmmReg
xmm11
;
//!< 128-bit Xmm register (X64).
ASMJIT_VAR
const
X86XmmReg
xmm12
;
//!< 128-bit Xmm register (X64).
ASMJIT_VAR
const
X86XmmReg
xmm13
;
//!< 128-bit Xmm register (X64).
ASMJIT_VAR
const
X86XmmReg
xmm14
;
//!< 128-bit Xmm register (X64).
ASMJIT_VAR
const
X86XmmReg
xmm15
;
//!< 128-bit Xmm register (X64).
ASMJIT_VAR
const
X86YmmReg
ymm0
;
//!< 256-bit Ymm register.
ASMJIT_VAR
const
X86YmmReg
ymm1
;
//!< 256-bit Ymm register.
ASMJIT_VAR
const
X86YmmReg
ymm2
;
//!< 256-bit Ymm register.
ASMJIT_VAR
const
X86YmmReg
ymm3
;
//!< 256-bit Ymm register.
ASMJIT_VAR
const
X86YmmReg
ymm4
;
//!< 256-bit Ymm register.
ASMJIT_VAR
const
X86YmmReg
ymm5
;
//!< 256-bit Ymm register.
ASMJIT_VAR
const
X86YmmReg
ymm6
;
//!< 256-bit Ymm register.
ASMJIT_VAR
const
X86YmmReg
ymm7
;
//!< 256-bit Ymm register.
ASMJIT_VAR
const
X86YmmReg
ymm8
;
//!< 256-bit Ymm register (X64).
ASMJIT_VAR
const
X86YmmReg
ymm9
;
//!< 256-bit Ymm register (X64).
ASMJIT_VAR
const
X86YmmReg
ymm10
;
//!< 256-bit Ymm register (X64).
ASMJIT_VAR
const
X86YmmReg
ymm11
;
//!< 256-bit Ymm register (X64).
ASMJIT_VAR
const
X86YmmReg
ymm12
;
//!< 256-bit Ymm register (X64).
ASMJIT_VAR
const
X86YmmReg
ymm13
;
//!< 256-bit Ymm register (X64).
ASMJIT_VAR
const
X86YmmReg
ymm14
;
//!< 256-bit Ymm register (X64).
ASMJIT_VAR
const
X86YmmReg
ymm15
;
//!< 256-bit Ymm register (X64).
ASMJIT_VAR
const
X86SegReg
cs
;
//!< Cs segment register.
ASMJIT_VAR
const
X86SegReg
ss
;
//!< Ss segment register.
ASMJIT_VAR
const
X86SegReg
ds
;
//!< Ds segment register.
ASMJIT_VAR
const
X86SegReg
es
;
//!< Es segment register.
ASMJIT_VAR
const
X86SegReg
fs
;
//!< Fs segment register.
ASMJIT_VAR
const
X86SegReg
gs
;
//!< Gs segment register.
// This is only defined by `x86operand_regs.cpp` when exporting registers.
#if !defined(ASMJIT_EXPORTS_X86OPERAND_REGS)
//! Create 8-bit Gpb-lo register operand.
static
ASMJIT_INLINE
X86GpReg
gpb_lo
(
uint32_t
index
)
{
return
X86GpReg
(
kX86RegTypeGpbLo
,
index
,
1
);
}
//! Create 8-bit Gpb-hi register operand.
static
ASMJIT_INLINE
X86GpReg
gpb_hi
(
uint32_t
index
)
{
return
X86GpReg
(
kX86RegTypeGpbHi
,
index
,
1
);
}
//! Create 16-bit Gpw register operand.
static
ASMJIT_INLINE
X86GpReg
gpw
(
uint32_t
index
)
{
return
X86GpReg
(
kX86RegTypeGpw
,
index
,
2
);
}
//! Create 32-bit Gpd register operand.
static
ASMJIT_INLINE
X86GpReg
gpd
(
uint32_t
index
)
{
return
X86GpReg
(
kX86RegTypeGpd
,
index
,
4
);
}
//! Create 64-bit Gpq register operand (X64).
static
ASMJIT_INLINE
X86GpReg
gpq
(
uint32_t
index
)
{
return
X86GpReg
(
kX86RegTypeGpq
,
index
,
8
);
}
//! Create 80-bit Fp register operand.
static
ASMJIT_INLINE
X86FpReg
fp
(
uint32_t
index
)
{
return
X86FpReg
(
kX86RegTypeFp
,
index
,
10
);
}
//! Create 64-bit Mm register operand.
static
ASMJIT_INLINE
X86MmReg
mm
(
uint32_t
index
)
{
return
X86MmReg
(
kX86RegTypeMm
,
index
,
8
);
}
//! Create 128-bit Xmm register operand.
static
ASMJIT_INLINE
X86XmmReg
xmm
(
uint32_t
index
)
{
return
X86XmmReg
(
kX86RegTypeXmm
,
index
,
16
);
}
//! Create 256-bit Ymm register operand.
static
ASMJIT_INLINE
X86YmmReg
ymm
(
uint32_t
index
)
{
return
X86YmmReg
(
kX86RegTypeYmm
,
index
,
32
);
}
// ============================================================================
// [asmjit::x86 - Ptr (Reg)]
// ============================================================================
//! Create `[base.reg + disp]` memory operand with no/custom size information.
static
ASMJIT_INLINE
X86Mem
ptr
(
const
X86GpReg
&
base
,
int32_t
disp
=
0
,
uint32_t
size
=
0
)
{
return
X86Mem
(
base
,
disp
,
size
);
}
//! Create `[base.reg + (index.reg << shift) + disp]` memory operand with no/custom size information.
static
ASMJIT_INLINE
X86Mem
ptr
(
const
X86GpReg
&
base
,
const
X86GpReg
&
index
,
uint32_t
shift
=
0
,
int32_t
disp
=
0
,
uint32_t
size
=
0
)
{
return
X86Mem
(
base
,
index
,
shift
,
disp
,
size
);
}
//! Create `[base.reg + (xmm.reg << shift) + disp]` memory operand with no/custom size information.
static
ASMJIT_INLINE
X86Mem
ptr
(
const
X86GpReg
&
base
,
const
X86XmmReg
&
index
,
uint32_t
shift
=
0
,
int32_t
disp
=
0
,
uint32_t
size
=
0
)
{
return
X86Mem
(
base
,
index
,
shift
,
disp
,
size
);
}
//! Create `[base.reg + (ymm.reg << shift) + disp]` memory operand with no/custom size information.
static
ASMJIT_INLINE
X86Mem
ptr
(
const
X86GpReg
&
base
,
const
X86YmmReg
&
index
,
uint32_t
shift
=
0
,
int32_t
disp
=
0
,
uint32_t
size
=
0
)
{
return
X86Mem
(
base
,
index
,
shift
,
disp
,
size
);
}
//! Create `[label + disp]` memory operand with no/custom size information.
static
ASMJIT_INLINE
X86Mem
ptr
(
const
Label
&
label
,
int32_t
disp
=
0
,
uint32_t
size
=
0
)
{
return
X86Mem
(
label
,
disp
,
size
);
}
//! Create `[label + (index.reg << shift) + disp]` memory operand with no/custom size information.
static
ASMJIT_INLINE
X86Mem
ptr
(
const
Label
&
label
,
const
X86GpReg
&
index
,
uint32_t
shift
,
int32_t
disp
=
0
,
uint32_t
size
=
0
)
{
\
return
X86Mem
(
label
,
index
,
shift
,
disp
,
size
);
\
}
//! Create `[pAbs + disp]` absolute memory operand with no/custom size information.
ASMJIT_API
X86Mem
ptr_abs
(
Ptr
pAbs
,
int32_t
disp
=
0
,
uint32_t
size
=
0
);
//! Create `[pAbs + (index.reg << shift) + disp]` absolute memory operand with no/custom size information.
ASMJIT_API
X86Mem
ptr_abs
(
Ptr
pAbs
,
const
X86Reg
&
index
,
uint32_t
shift
=
0
,
int32_t
disp
=
0
,
uint32_t
size
=
0
);
//! \internal
#define ASMJIT_EXPAND_PTR_REG(_Prefix_, _Size_) \
/*! Create `[base.reg + disp]` memory operand. */
\
static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const X86GpReg& base, int32_t disp = 0) { \
return X86Mem(base, disp, _Size_); \
} \
/*! Create `[base.reg + (index.reg << shift) + disp]` memory operand. */
\
static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const X86GpReg& base, const X86GpReg& index, uint32_t shift = 0, int32_t disp = 0) { \
return ptr(base, index, shift, disp, _Size_); \
} \
/*! Create `[base.reg + (xmm.reg << shift) + disp]` memory operand. */
\
static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const X86GpReg& base, const X86XmmReg& index, uint32_t shift = 0, int32_t disp = 0) { \
return ptr(base, index, shift, disp, _Size_); \
} \
/*! Create `[base.reg + (ymm.reg << shift) + disp]` memory operand. */
\
static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const X86GpReg& base, const X86YmmReg& index, uint32_t shift = 0, int32_t disp = 0) { \
return ptr(base, index, shift, disp, _Size_); \
} \
/*! Create `[label + disp]` memory operand. */
\
static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const Label& label, int32_t disp = 0) { \
return ptr(label, disp, _Size_); \
} \
/*! Create `[label + (index.reg << shift) + disp]` memory operand. */
\
static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const Label& label, const X86GpReg& index, uint32_t shift, int32_t disp = 0) { \
return ptr(label, index, shift, disp, _Size_); \
} \
/*! Create `[pAbs + disp]` memory operand. */
\
static ASMJIT_INLINE X86Mem _Prefix_##_ptr##_abs(Ptr pAbs, int32_t disp = 0) { \
return ptr_abs(pAbs, disp, _Size_); \
} \
/*! Create `[pAbs + (index.reg << shift) + disp]` memory operand. */
\
static ASMJIT_INLINE X86Mem _Prefix_##_ptr##_abs(Ptr pAbs, const X86GpReg& index, uint32_t shift = 0, int32_t disp = 0) { \
return ptr_abs(pAbs, index, shift, disp, _Size_); \
} \
/*! Create `[pAbs + (xmm.reg << shift) + disp]` memory operand. */
\
static ASMJIT_INLINE X86Mem _Prefix_##_ptr##_abs(Ptr pAbs, const X86XmmReg& index, uint32_t shift = 0, int32_t disp = 0) { \
return ptr_abs(pAbs, index, shift, disp, _Size_); \
} \
/*! Create `[pAbs + (ymm.reg << shift) + disp]` memory operand. */
\
static ASMJIT_INLINE X86Mem _Prefix_##_ptr##_abs(Ptr pAbs, const X86YmmReg& index, uint32_t shift = 0, int32_t disp = 0) { \
return ptr_abs(pAbs, index, shift, disp, _Size_); \
}
ASMJIT_EXPAND_PTR_REG
(
byte
,
1
)
ASMJIT_EXPAND_PTR_REG
(
word
,
2
)
ASMJIT_EXPAND_PTR_REG
(
dword
,
4
)
ASMJIT_EXPAND_PTR_REG
(
qword
,
8
)
ASMJIT_EXPAND_PTR_REG
(
tword
,
10
)
ASMJIT_EXPAND_PTR_REG
(
oword
,
16
)
ASMJIT_EXPAND_PTR_REG
(
yword
,
32
)
ASMJIT_EXPAND_PTR_REG
(
zword
,
64
)
#undef ASMJIT_EXPAND_PTR_REG
// ============================================================================
// [asmjit::x86 - Ptr (Var)]
// ============================================================================
#if !defined(ASMJIT_DISABLE_COMPILER)
//! Create `[base.var + disp]` memory operand with no/custom size information.
static
ASMJIT_INLINE
X86Mem
ptr
(
const
X86GpVar
&
base
,
int32_t
disp
=
0
,
uint32_t
size
=
0
)
{
return
X86Mem
(
base
,
disp
,
size
);
}
//! Create `[base.var + (index.var << shift) + disp]` memory operand with no/custom size information.
static
ASMJIT_INLINE
X86Mem
ptr
(
const
X86GpVar
&
base
,
const
X86GpVar
&
index
,
uint32_t
shift
=
0
,
int32_t
disp
=
0
,
uint32_t
size
=
0
)
{
return
X86Mem
(
base
,
index
,
shift
,
disp
,
size
);
}
//! Create `[base.var + (xmm.var << shift) + disp]` memory operand with no/custom size information.
static
ASMJIT_INLINE
X86Mem
ptr
(
const
X86GpVar
&
base
,
const
X86XmmVar
&
index
,
uint32_t
shift
=
0
,
int32_t
disp
=
0
,
uint32_t
size
=
0
)
{
return
X86Mem
(
base
,
index
,
shift
,
disp
,
size
);
}
//! Create `[base.var + (ymm.var << shift) + disp]` memory operand with no/custom size information.
static
ASMJIT_INLINE
X86Mem
ptr
(
const
X86GpVar
&
base
,
const
X86YmmVar
&
index
,
uint32_t
shift
=
0
,
int32_t
disp
=
0
,
uint32_t
size
=
0
)
{
return
X86Mem
(
base
,
index
,
shift
,
disp
,
size
);
}
//! Create `[label + (index.var << shift) + disp]` memory operand with no/custom size information.
static
ASMJIT_INLINE
X86Mem
ptr
(
const
Label
&
label
,
const
X86GpVar
&
index
,
uint32_t
shift
,
int32_t
disp
=
0
,
uint32_t
size
=
0
)
{
\
return
X86Mem
(
label
,
index
,
shift
,
disp
,
size
);
\
}
//! Create `[pAbs + (index.var << shift) + disp]` absolute memory operand with no/custom size information.
ASMJIT_API
X86Mem
ptr_abs
(
Ptr
pAbs
,
const
X86Var
&
index
,
uint32_t
shift
=
0
,
int32_t
disp
=
0
,
uint32_t
size
=
0
);
//! \internal
#define ASMJIT_EXPAND_PTR_VAR(_Prefix_, _Size_) \
/*! Create `[base.var + disp]` memory operand. */
\
static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const X86GpVar& base, int32_t disp = 0) { \
return X86Mem(base, disp, _Size_); \
} \
/*! Create `[base.var + (index.var << shift) + disp]` memory operand. */
\
static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const X86GpVar& base, const X86GpVar& index, uint32_t shift = 0, int32_t disp = 0) { \
return ptr(base, index, shift, disp, _Size_); \
} \
/*! Create `[base.var + (xmm.var << shift) + disp]` memory operand. */
\
static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const X86GpVar& base, const X86XmmVar& index, uint32_t shift = 0, int32_t disp = 0) { \
return ptr(base, index, shift, disp, _Size_); \
} \
/*! Create `[base.var + (ymm.var << shift) + disp]` memory operand. */
\
static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const X86GpVar& base, const X86YmmVar& index, uint32_t shift = 0, int32_t disp = 0) { \
return ptr(base, index, shift, disp, _Size_); \
} \
/*! Create `[label + (index.var << shift) + disp]` memory operand. */
\
static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const Label& label, const X86GpVar& index, uint32_t shift, int32_t disp = 0) { \
return ptr(label, index, shift, disp, _Size_); \
} \
/*! Create `[pAbs + (index.var << shift) + disp]` memory operand. */
\
static ASMJIT_INLINE X86Mem _Prefix_##_ptr##_abs(Ptr pAbs, const X86GpVar& index, uint32_t shift = 0, int32_t disp = 0) { \
return ptr_abs(pAbs, reinterpret_cast<const X86Var&>(index), shift, disp, _Size_); \
} \
/*! Create `[pAbs + (xmm.var << shift) + disp]` memory operand. */
\
static ASMJIT_INLINE X86Mem _Prefix_##_ptr##_abs(Ptr pAbs, const X86XmmVar& index, uint32_t shift = 0, int32_t disp = 0) { \
return ptr_abs(pAbs, reinterpret_cast<const X86Var&>(index), shift, disp, _Size_); \
} \
/*! Create `[pAbs + (ymm.var << shift) + disp]` memory operand. */
\
static ASMJIT_INLINE X86Mem _Prefix_##_ptr##_abs(Ptr pAbs, const X86YmmVar& index, uint32_t shift = 0, int32_t disp = 0) { \
return ptr_abs(pAbs, reinterpret_cast<const X86Var&>(index), shift, disp, _Size_); \
}
ASMJIT_EXPAND_PTR_VAR
(
byte
,
1
)
ASMJIT_EXPAND_PTR_VAR
(
word
,
2
)
ASMJIT_EXPAND_PTR_VAR
(
dword
,
4
)
ASMJIT_EXPAND_PTR_VAR
(
qword
,
8
)
ASMJIT_EXPAND_PTR_VAR
(
tword
,
10
)
ASMJIT_EXPAND_PTR_VAR
(
oword
,
16
)
ASMJIT_EXPAND_PTR_VAR
(
yword
,
32
)
ASMJIT_EXPAND_PTR_VAR
(
zword
,
64
)
#undef ASMJIT_EXPAND_PTR_VAR
#endif // !ASMJIT_DISABLE_COMPILER
#endif // !ASMJIT_EXPORTS_X86OPERAND_REGS
}
// x86 namespace
//! \}
}
// asmjit namespace
#undef _OP_ID
// [Api-End]
#include "../apiend.h"
// [Guard]
#endif // _ASMJIT_X86_X86OPERAND_H
libraries/asmjit/x86/x86operand_regs.cpp
0 → 100644
View file @
751ff079
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Export]
#define ASMJIT_EXPORTS
#define ASMJIT_EXPORTS_X86OPERAND_REGS
// [Guard]
#include "../build.h"
#if defined(ASMJIT_BUILD_X86) || defined(ASMJIT_BUILD_X64)
// [Dependencies - AsmJit]
#include "../x86/x86operand.h"
// [Api-Begin]
#include "../apibegin.h"
namespace
asmjit
{
// Prevent static initialization.
//
// Remap all classes to POD structs so they can be statically initialized
// without calling a constructor. Compiler will store these in data section.
struct
X86GpReg
{
Operand
::
VRegOp
data
;
};
struct
X86FpReg
{
Operand
::
VRegOp
data
;
};
struct
X86MmReg
{
Operand
::
VRegOp
data
;
};
struct
X86XmmReg
{
Operand
::
VRegOp
data
;
};
struct
X86YmmReg
{
Operand
::
VRegOp
data
;
};
struct
X86SegReg
{
Operand
::
VRegOp
data
;
};
namespace
x86
{
// ============================================================================
// [asmjit::x86::Registers]
// ============================================================================
#define REG(_Class_, _Name_, _Type_, _Index_, _Size_) \
const _Class_ _Name_ = {{ \
kOperandTypeReg, _Size_, { ((_Type_) << 8) + _Index_ }, kInvalidValue, {{ kInvalidVar, 0 }} \
}}
REG
(
X86GpReg
,
noGpReg
,
kInvalidReg
,
kInvalidReg
,
0
);
REG
(
X86GpReg
,
al
,
kX86RegTypeGpbLo
,
kX86RegIndexAx
,
1
);
REG
(
X86GpReg
,
cl
,
kX86RegTypeGpbLo
,
kX86RegIndexCx
,
1
);
REG
(
X86GpReg
,
dl
,
kX86RegTypeGpbLo
,
kX86RegIndexDx
,
1
);
REG
(
X86GpReg
,
bl
,
kX86RegTypeGpbLo
,
kX86RegIndexBx
,
1
);
REG
(
X86GpReg
,
spl
,
kX86RegTypeGpbLo
,
kX86RegIndexSp
,
1
);
REG
(
X86GpReg
,
bpl
,
kX86RegTypeGpbLo
,
kX86RegIndexBp
,
1
);
REG
(
X86GpReg
,
sil
,
kX86RegTypeGpbLo
,
kX86RegIndexSi
,
1
);
REG
(
X86GpReg
,
dil
,
kX86RegTypeGpbLo
,
kX86RegIndexDi
,
1
);
REG
(
X86GpReg
,
r8b
,
kX86RegTypeGpbLo
,
8
,
1
);
REG
(
X86GpReg
,
r9b
,
kX86RegTypeGpbLo
,
9
,
1
);
REG
(
X86GpReg
,
r10b
,
kX86RegTypeGpbLo
,
10
,
1
);
REG
(
X86GpReg
,
r11b
,
kX86RegTypeGpbLo
,
11
,
1
);
REG
(
X86GpReg
,
r12b
,
kX86RegTypeGpbLo
,
12
,
1
);
REG
(
X86GpReg
,
r13b
,
kX86RegTypeGpbLo
,
13
,
1
);
REG
(
X86GpReg
,
r14b
,
kX86RegTypeGpbLo
,
14
,
1
);
REG
(
X86GpReg
,
r15b
,
kX86RegTypeGpbLo
,
15
,
1
);
REG
(
X86GpReg
,
ah
,
kX86RegTypeGpbHi
,
kX86RegIndexAx
,
1
);
REG
(
X86GpReg
,
ch
,
kX86RegTypeGpbHi
,
kX86RegIndexCx
,
1
);
REG
(
X86GpReg
,
dh
,
kX86RegTypeGpbHi
,
kX86RegIndexDx
,
1
);
REG
(
X86GpReg
,
bh
,
kX86RegTypeGpbHi
,
kX86RegIndexBx
,
1
);
REG
(
X86GpReg
,
ax
,
kX86RegTypeGpw
,
kX86RegIndexAx
,
2
);
REG
(
X86GpReg
,
cx
,
kX86RegTypeGpw
,
kX86RegIndexCx
,
2
);
REG
(
X86GpReg
,
dx
,
kX86RegTypeGpw
,
kX86RegIndexDx
,
2
);
REG
(
X86GpReg
,
bx
,
kX86RegTypeGpw
,
kX86RegIndexBx
,
2
);
REG
(
X86GpReg
,
sp
,
kX86RegTypeGpw
,
kX86RegIndexSp
,
2
);
REG
(
X86GpReg
,
bp
,
kX86RegTypeGpw
,
kX86RegIndexBp
,
2
);
REG
(
X86GpReg
,
si
,
kX86RegTypeGpw
,
kX86RegIndexSi
,
2
);
REG
(
X86GpReg
,
di
,
kX86RegTypeGpw
,
kX86RegIndexDi
,
2
);
REG
(
X86GpReg
,
r8w
,
kX86RegTypeGpw
,
8
,
2
);
REG
(
X86GpReg
,
r9w
,
kX86RegTypeGpw
,
9
,
2
);
REG
(
X86GpReg
,
r10w
,
kX86RegTypeGpw
,
10
,
2
);
REG
(
X86GpReg
,
r11w
,
kX86RegTypeGpw
,
11
,
2
);
REG
(
X86GpReg
,
r12w
,
kX86RegTypeGpw
,
12
,
2
);
REG
(
X86GpReg
,
r13w
,
kX86RegTypeGpw
,
13
,
2
);
REG
(
X86GpReg
,
r14w
,
kX86RegTypeGpw
,
14
,
2
);
REG
(
X86GpReg
,
r15w
,
kX86RegTypeGpw
,
15
,
2
);
REG
(
X86GpReg
,
eax
,
kX86RegTypeGpd
,
kX86RegIndexAx
,
4
);
REG
(
X86GpReg
,
ecx
,
kX86RegTypeGpd
,
kX86RegIndexCx
,
4
);
REG
(
X86GpReg
,
edx
,
kX86RegTypeGpd
,
kX86RegIndexDx
,
4
);
REG
(
X86GpReg
,
ebx
,
kX86RegTypeGpd
,
kX86RegIndexBx
,
4
);
REG
(
X86GpReg
,
esp
,
kX86RegTypeGpd
,
kX86RegIndexSp
,
4
);
REG
(
X86GpReg
,
ebp
,
kX86RegTypeGpd
,
kX86RegIndexBp
,
4
);
REG
(
X86GpReg
,
esi
,
kX86RegTypeGpd
,
kX86RegIndexSi
,
4
);
REG
(
X86GpReg
,
edi
,
kX86RegTypeGpd
,
kX86RegIndexDi
,
4
);
REG
(
X86GpReg
,
r8d
,
kX86RegTypeGpd
,
8
,
4
);
REG
(
X86GpReg
,
r9d
,
kX86RegTypeGpd
,
9
,
4
);
REG
(
X86GpReg
,
r10d
,
kX86RegTypeGpd
,
10
,
4
);
REG
(
X86GpReg
,
r11d
,
kX86RegTypeGpd
,
11
,
4
);
REG
(
X86GpReg
,
r12d
,
kX86RegTypeGpd
,
12
,
4
);
REG
(
X86GpReg
,
r13d
,
kX86RegTypeGpd
,
13
,
4
);
REG
(
X86GpReg
,
r14d
,
kX86RegTypeGpd
,
14
,
4
);
REG
(
X86GpReg
,
r15d
,
kX86RegTypeGpd
,
15
,
4
);
REG
(
X86GpReg
,
rax
,
kX86RegTypeGpq
,
kX86RegIndexAx
,
8
);
REG
(
X86GpReg
,
rcx
,
kX86RegTypeGpq
,
kX86RegIndexCx
,
8
);
REG
(
X86GpReg
,
rdx
,
kX86RegTypeGpq
,
kX86RegIndexDx
,
8
);
REG
(
X86GpReg
,
rbx
,
kX86RegTypeGpq
,
kX86RegIndexBx
,
8
);
REG
(
X86GpReg
,
rsp
,
kX86RegTypeGpq
,
kX86RegIndexSp
,
8
);
REG
(
X86GpReg
,
rbp
,
kX86RegTypeGpq
,
kX86RegIndexBp
,
8
);
REG
(
X86GpReg
,
rsi
,
kX86RegTypeGpq
,
kX86RegIndexSi
,
8
);
REG
(
X86GpReg
,
rdi
,
kX86RegTypeGpq
,
kX86RegIndexDi
,
8
);
REG
(
X86GpReg
,
r8
,
kX86RegTypeGpq
,
8
,
8
);
REG
(
X86GpReg
,
r9
,
kX86RegTypeGpq
,
9
,
8
);
REG
(
X86GpReg
,
r10
,
kX86RegTypeGpq
,
10
,
8
);
REG
(
X86GpReg
,
r11
,
kX86RegTypeGpq
,
11
,
8
);
REG
(
X86GpReg
,
r12
,
kX86RegTypeGpq
,
12
,
8
);
REG
(
X86GpReg
,
r13
,
kX86RegTypeGpq
,
13
,
8
);
REG
(
X86GpReg
,
r14
,
kX86RegTypeGpq
,
14
,
8
);
REG
(
X86GpReg
,
r15
,
kX86RegTypeGpq
,
15
,
8
);
REG
(
X86FpReg
,
fp0
,
kX86RegTypeFp
,
0
,
10
);
REG
(
X86FpReg
,
fp1
,
kX86RegTypeFp
,
1
,
10
);
REG
(
X86FpReg
,
fp2
,
kX86RegTypeFp
,
2
,
10
);
REG
(
X86FpReg
,
fp3
,
kX86RegTypeFp
,
3
,
10
);
REG
(
X86FpReg
,
fp4
,
kX86RegTypeFp
,
4
,
10
);
REG
(
X86FpReg
,
fp5
,
kX86RegTypeFp
,
5
,
10
);
REG
(
X86FpReg
,
fp6
,
kX86RegTypeFp
,
6
,
10
);
REG
(
X86FpReg
,
fp7
,
kX86RegTypeFp
,
7
,
10
);
REG
(
X86MmReg
,
mm0
,
kX86RegTypeMm
,
0
,
8
);
REG
(
X86MmReg
,
mm1
,
kX86RegTypeMm
,
1
,
8
);
REG
(
X86MmReg
,
mm2
,
kX86RegTypeMm
,
2
,
8
);
REG
(
X86MmReg
,
mm3
,
kX86RegTypeMm
,
3
,
8
);
REG
(
X86MmReg
,
mm4
,
kX86RegTypeMm
,
4
,
8
);
REG
(
X86MmReg
,
mm5
,
kX86RegTypeMm
,
5
,
8
);
REG
(
X86MmReg
,
mm6
,
kX86RegTypeMm
,
6
,
8
);
REG
(
X86MmReg
,
mm7
,
kX86RegTypeMm
,
7
,
8
);
REG
(
X86XmmReg
,
xmm0
,
kX86RegTypeXmm
,
0
,
16
);
REG
(
X86XmmReg
,
xmm1
,
kX86RegTypeXmm
,
1
,
16
);
REG
(
X86XmmReg
,
xmm2
,
kX86RegTypeXmm
,
2
,
16
);
REG
(
X86XmmReg
,
xmm3
,
kX86RegTypeXmm
,
3
,
16
);
REG
(
X86XmmReg
,
xmm4
,
kX86RegTypeXmm
,
4
,
16
);
REG
(
X86XmmReg
,
xmm5
,
kX86RegTypeXmm
,
5
,
16
);
REG
(
X86XmmReg
,
xmm6
,
kX86RegTypeXmm
,
6
,
16
);
REG
(
X86XmmReg
,
xmm7
,
kX86RegTypeXmm
,
7
,
16
);
REG
(
X86XmmReg
,
xmm8
,
kX86RegTypeXmm
,
8
,
16
);
REG
(
X86XmmReg
,
xmm9
,
kX86RegTypeXmm
,
9
,
16
);
REG
(
X86XmmReg
,
xmm10
,
kX86RegTypeXmm
,
10
,
16
);
REG
(
X86XmmReg
,
xmm11
,
kX86RegTypeXmm
,
11
,
16
);
REG
(
X86XmmReg
,
xmm12
,
kX86RegTypeXmm
,
12
,
16
);
REG
(
X86XmmReg
,
xmm13
,
kX86RegTypeXmm
,
13
,
16
);
REG
(
X86XmmReg
,
xmm14
,
kX86RegTypeXmm
,
14
,
16
);
REG
(
X86XmmReg
,
xmm15
,
kX86RegTypeXmm
,
15
,
16
);
REG
(
X86YmmReg
,
ymm0
,
kX86RegTypeYmm
,
0
,
32
);
REG
(
X86YmmReg
,
ymm1
,
kX86RegTypeYmm
,
1
,
32
);
REG
(
X86YmmReg
,
ymm2
,
kX86RegTypeYmm
,
2
,
32
);
REG
(
X86YmmReg
,
ymm3
,
kX86RegTypeYmm
,
3
,
32
);
REG
(
X86YmmReg
,
ymm4
,
kX86RegTypeYmm
,
4
,
32
);
REG
(
X86YmmReg
,
ymm5
,
kX86RegTypeYmm
,
5
,
32
);
REG
(
X86YmmReg
,
ymm6
,
kX86RegTypeYmm
,
6
,
32
);
REG
(
X86YmmReg
,
ymm7
,
kX86RegTypeYmm
,
7
,
32
);
REG
(
X86YmmReg
,
ymm8
,
kX86RegTypeYmm
,
8
,
32
);
REG
(
X86YmmReg
,
ymm9
,
kX86RegTypeYmm
,
9
,
32
);
REG
(
X86YmmReg
,
ymm10
,
kX86RegTypeYmm
,
10
,
32
);
REG
(
X86YmmReg
,
ymm11
,
kX86RegTypeYmm
,
11
,
32
);
REG
(
X86YmmReg
,
ymm12
,
kX86RegTypeYmm
,
12
,
32
);
REG
(
X86YmmReg
,
ymm13
,
kX86RegTypeYmm
,
13
,
32
);
REG
(
X86YmmReg
,
ymm14
,
kX86RegTypeYmm
,
14
,
32
);
REG
(
X86YmmReg
,
ymm15
,
kX86RegTypeYmm
,
15
,
32
);
REG
(
X86SegReg
,
cs
,
kX86RegTypeSeg
,
kX86SegCs
,
2
);
REG
(
X86SegReg
,
ss
,
kX86RegTypeSeg
,
kX86SegSs
,
2
);
REG
(
X86SegReg
,
ds
,
kX86RegTypeSeg
,
kX86SegDs
,
2
);
REG
(
X86SegReg
,
es
,
kX86RegTypeSeg
,
kX86SegEs
,
2
);
REG
(
X86SegReg
,
fs
,
kX86RegTypeSeg
,
kX86SegFs
,
2
);
REG
(
X86SegReg
,
gs
,
kX86RegTypeSeg
,
kX86SegGs
,
2
);
#undef REG
}
// x86 namespace
}
// asmjit namespace
// [Api-End]
#include "../apiend.h"
// [Guard]
#endif // ASMJIT_BUILD_X86 || ASMJIT_BUILD_X64
libraries/asmjit/x86/x86scheduler.cpp
0 → 100644
View file @
751ff079
// [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) && (defined(ASMJIT_BUILD_X86) || defined(ASMJIT_BUILD_X64))
// [Dependencies - AsmJit]
#include "../base/containers.h"
#include "../x86/x86scheduler_p.h"
// [Api-Begin]
#include "../apibegin.h"
namespace
asmjit
{
// ============================================================================
// [Internals]
// ============================================================================
//! \internal
struct
X86ScheduleData
{
//! Registers read by the instruction.
X86RegMask
regsIn
;
//! Registers written by the instruction.
X86RegMask
regsOut
;
//! Flags read by the instruction.
uint8_t
flagsIn
;
//! Flags written by the instruction.
uint8_t
flagsOut
;
//! How many `uops` or `cycles` the instruction takes.
uint8_t
ops
;
//! Instruction latency.
uint8_t
latency
;
//! Which ports the instruction can run at.
uint16_t
ports
;
//! \internal
uint16_t
reserved
;
//! All instructions that this instruction depends on.
PodList
<
InstNode
*>::
Link
*
dependsOn
;
//! All instructions that use the result of this instruction.
PodList
<
InstNode
*>::
Link
*
usedBy
;
};
// ============================================================================
// [asmjit::X86Scheduler - Construction / Destruction]
// ============================================================================
X86Scheduler
::
X86Scheduler
(
X86Compiler
*
compiler
,
const
X86CpuInfo
*
cpuInfo
)
:
_compiler
(
compiler
),
_cpuInfo
(
cpuInfo
)
{}
X86Scheduler
::~
X86Scheduler
()
{}
// ============================================================================
// [asmjit::X86Scheduler - Run]
// ============================================================================
Error
X86Scheduler
::
run
(
Node
*
start
,
Node
*
stop
)
{
/*
ASMJIT_TLOG("[Schedule] === Begin ===");
Zone zone(8096 - kZoneOverhead);
Node* node_ = start;
while (node_ != stop) {
Node* next = node_->getNext();
ASMJIT_ASSERT(node_->getType() == kNodeTypeInst);
printf(" %s\n", X86Util::getInstInfo(static_cast<InstNode*>(node_)->getCode()).getInstName());
node_ = next;
}
ASMJIT_TLOG("[Schedule] === End ===");
*/
return
kErrorOk
;
}
}
// asmjit namespace
// [Api-End]
#include "../apiend.h"
// [Guard]
#endif // !ASMJIT_DISABLE_COMPILER && (ASMJIT_BUILD_X86 || ASMJIT_BUILD_X64)
libraries/asmjit/x86/x86scheduler_p.h
0 → 100644
View file @
751ff079
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Guard]
#ifndef _ASMJIT_X86_X86SCHEDULER_P_H
#define _ASMJIT_X86_X86SCHEDULER_P_H
#include "../build.h"
#if !defined(ASMJIT_DISABLE_COMPILER)
// [Dependencies - AsmJit]
#include "../x86/x86compiler.h"
#include "../x86/x86context_p.h"
#include "../x86/x86cpuinfo.h"
#include "../x86/x86inst.h"
// [Api-Begin]
#include "../apibegin.h"
namespace
asmjit
{
// ============================================================================
// [asmjit::X86Scheduler]
// ============================================================================
//! \internal
//!
//! X86 scheduler.
struct
X86Scheduler
{
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
X86Scheduler
(
X86Compiler
*
compiler
,
const
X86CpuInfo
*
cpuInfo
);
~
X86Scheduler
();
// --------------------------------------------------------------------------
// [Run]
// --------------------------------------------------------------------------
Error
run
(
Node
*
start
,
Node
*
stop
);
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
//! Attached compiler.
X86Compiler
*
_compiler
;
//! CPU information used for scheduling.
const
X86CpuInfo
*
_cpuInfo
;
};
}
// asmjit namespace
// [Api-End]
#include "../apiend.h"
// [Guard]
#endif // !ASMJIT_DISABLE_COMPILER
#endif // _ASMJIT_X86_X86SCHEDULER_P_H
libraries/lepton/include/lepton/CompiledExpression.h
View file @
751ff079
...
...
@@ -38,6 +38,9 @@
#include <set>
#include <string>
#include <vector>
#ifdef LEPTON_USE_JIT
#include "asmjit.h"
#endif
namespace
Lepton
{
...
...
@@ -87,6 +90,13 @@ private:
mutable
std
::
vector
<
double
>
workspace
;
mutable
std
::
vector
<
double
>
argValues
;
std
::
map
<
std
::
string
,
double
>
dummyVariables
;
void
*
jitCode
;
#ifdef LEPTON_USE_JIT
void
generateJitCode
();
void
generateSingleArgCall
(
asmjit
::
X86Compiler
&
c
,
asmjit
::
X86XmmVar
&
dest
,
asmjit
::
X86XmmVar
&
arg
,
double
(
*
function
)(
double
));
std
::
vector
<
double
>
constants
;
asmjit
::
JitRuntime
runtime
;
#endif
};
}
// namespace Lepton
...
...
libraries/lepton/src/CompiledExpression.cpp
View file @
751ff079
/* -------------------------------------------------------------------------- *
* Lepton *
* -------------------------------------------------------------------------- *
* This is part of the Lepton expression parser originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2013 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "lepton/CompiledExpression.h"
#include "lepton/Operation.h"
#include "lepton/ParsedExpression.h"
#include <utility>
using
namespace
Lepton
;
using
namespace
std
;
CompiledExpression
::
CompiledExpression
()
{
}
CompiledExpression
::
CompiledExpression
(
const
ParsedExpression
&
expression
)
{
ParsedExpression
expr
=
expression
.
optimize
();
// Just in case it wasn't already optimized.
vector
<
pair
<
ExpressionTreeNode
,
int
>
>
temps
;
compileExpression
(
expr
.
getRootNode
(),
temps
);
}
CompiledExpression
::~
CompiledExpression
()
{
for
(
int
i
=
0
;
i
<
(
int
)
operation
.
size
();
i
++
)
if
(
operation
[
i
]
!=
NULL
)
delete
operation
[
i
];
}
CompiledExpression
::
CompiledExpression
(
const
CompiledExpression
&
expression
)
{
*
this
=
expression
;
}
CompiledExpression
&
CompiledExpression
::
operator
=
(
const
CompiledExpression
&
expression
)
{
arguments
=
expression
.
arguments
;
target
=
expression
.
target
;
variableIndices
=
expression
.
variableIndices
;
variableNames
=
expression
.
variableNames
;
workspace
.
resize
(
expression
.
workspace
.
size
());
argValues
.
resize
(
expression
.
argValues
.
size
());
operation
.
resize
(
expression
.
operation
.
size
());
for
(
int
i
=
0
;
i
<
(
int
)
operation
.
size
();
i
++
)
operation
[
i
]
=
expression
.
operation
[
i
]
->
clone
();
return
*
this
;
}
void
CompiledExpression
::
compileExpression
(
const
ExpressionTreeNode
&
node
,
vector
<
pair
<
ExpressionTreeNode
,
int
>
>&
temps
)
{
if
(
findTempIndex
(
node
,
temps
)
!=
-
1
)
return
;
// We have already processed a node identical to this one.
// Process the child nodes.
vector
<
int
>
args
;
for
(
int
i
=
0
;
i
<
node
.
getChildren
().
size
();
i
++
)
{
compileExpression
(
node
.
getChildren
()[
i
],
temps
);
args
.
push_back
(
findTempIndex
(
node
.
getChildren
()[
i
],
temps
));
}
// Process this node.
if
(
node
.
getOperation
().
getId
()
==
Operation
::
VARIABLE
)
{
variableIndices
[
node
.
getOperation
().
getName
()]
=
(
int
)
workspace
.
size
();
variableNames
.
insert
(
node
.
getOperation
().
getName
());
}
else
{
int
stepIndex
=
(
int
)
arguments
.
size
();
arguments
.
push_back
(
vector
<
int
>
());
target
.
push_back
((
int
)
workspace
.
size
());
operation
.
push_back
(
node
.
getOperation
().
clone
());
if
(
args
.
size
()
==
0
)
arguments
[
stepIndex
].
push_back
(
0
);
// The value won't actually be used. We just need something there.
else
{
// If the arguments are sequential, we can just pass a pointer to the first one.
bool
sequential
=
true
;
for
(
int
i
=
1
;
i
<
args
.
size
();
i
++
)
if
(
args
[
i
]
!=
args
[
i
-
1
]
+
1
)
sequential
=
false
;
if
(
sequential
)
arguments
[
stepIndex
].
push_back
(
args
[
0
]);
else
{
arguments
[
stepIndex
]
=
args
;
if
(
args
.
size
()
>
argValues
.
size
())
argValues
.
resize
(
args
.
size
(),
0.0
);
}
}
}
temps
.
push_back
(
make_pair
(
node
,
workspace
.
size
()));
workspace
.
push_back
(
0.0
);
}
int
CompiledExpression
::
findTempIndex
(
const
ExpressionTreeNode
&
node
,
vector
<
pair
<
ExpressionTreeNode
,
int
>
>&
temps
)
{
for
(
int
i
=
0
;
i
<
(
int
)
temps
.
size
();
i
++
)
if
(
temps
[
i
].
first
==
node
)
return
i
;
return
-
1
;
}
const
set
<
string
>&
CompiledExpression
::
getVariables
()
const
{
return
variableNames
;
}
double
&
CompiledExpression
::
getVariableReference
(
const
string
&
name
)
{
map
<
string
,
int
>::
iterator
index
=
variableIndices
.
find
(
name
);
if
(
index
==
variableIndices
.
end
())
throw
Exception
(
"getVariableReference: Unknown variable '"
+
name
+
"'"
);
return
workspace
[
index
->
second
];
}
double
CompiledExpression
::
evaluate
()
const
{
// Loop over the operations and evaluate each one.
for
(
int
step
=
0
;
step
<
operation
.
size
();
step
++
)
{
const
vector
<
int
>&
args
=
arguments
[
step
];
if
(
args
.
size
()
==
1
)
workspace
[
target
[
step
]]
=
operation
[
step
]
->
evaluate
(
&
workspace
[
args
[
0
]],
dummyVariables
);
else
{
for
(
int
i
=
0
;
i
<
args
.
size
();
i
++
)
argValues
[
i
]
=
workspace
[
args
[
i
]];
workspace
[
target
[
step
]]
=
operation
[
step
]
->
evaluate
(
&
argValues
[
0
],
dummyVariables
);
}
}
return
workspace
[
workspace
.
size
()
-
1
];
}
/* -------------------------------------------------------------------------- *
* Lepton *
* -------------------------------------------------------------------------- *
* This is part of the Lepton expression parser originating from *
* Simbios, the NIH National Center for Physics-Based Simulation of *
* Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. *
* *
* Portions copyright (c) 2013 Stanford University and the Authors. *
* Authors: Peter Eastman *
* Contributors: *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#include "lepton/CompiledExpression.h"
#include "lepton/Operation.h"
#include "lepton/ParsedExpression.h"
#include <utility>
using
namespace
Lepton
;
using
namespace
std
;
#ifdef LEPTON_USE_JIT
using
namespace
asmjit
;
#endif
CompiledExpression
::
CompiledExpression
()
:
jitCode
(
NULL
)
{
}
CompiledExpression
::
CompiledExpression
(
const
ParsedExpression
&
expression
)
:
jitCode
(
NULL
)
{
ParsedExpression
expr
=
expression
.
optimize
();
// Just in case it wasn't already optimized.
vector
<
pair
<
ExpressionTreeNode
,
int
>
>
temps
;
compileExpression
(
expr
.
getRootNode
(),
temps
);
int
maxArguments
=
1
;
for
(
int
i
=
0
;
i
<
(
int
)
operation
.
size
();
i
++
)
if
(
operation
[
i
]
->
getNumArguments
()
>
maxArguments
)
maxArguments
=
operation
[
i
]
->
getNumArguments
();
argValues
.
resize
(
maxArguments
);
#ifdef LEPTON_USE_JIT
generateJitCode
();
#endif
}
CompiledExpression
::~
CompiledExpression
()
{
for
(
int
i
=
0
;
i
<
(
int
)
operation
.
size
();
i
++
)
if
(
operation
[
i
]
!=
NULL
)
delete
operation
[
i
];
}
CompiledExpression
::
CompiledExpression
(
const
CompiledExpression
&
expression
)
:
jitCode
(
NULL
)
{
*
this
=
expression
;
}
CompiledExpression
&
CompiledExpression
::
operator
=
(
const
CompiledExpression
&
expression
)
{
arguments
=
expression
.
arguments
;
target
=
expression
.
target
;
variableIndices
=
expression
.
variableIndices
;
variableNames
=
expression
.
variableNames
;
workspace
.
resize
(
expression
.
workspace
.
size
());
argValues
.
resize
(
expression
.
argValues
.
size
());
operation
.
resize
(
expression
.
operation
.
size
());
for
(
int
i
=
0
;
i
<
(
int
)
operation
.
size
();
i
++
)
operation
[
i
]
=
expression
.
operation
[
i
]
->
clone
();
#ifdef LEPTON_USE_JIT
generateJitCode
();
#endif
return
*
this
;
}
void
CompiledExpression
::
compileExpression
(
const
ExpressionTreeNode
&
node
,
vector
<
pair
<
ExpressionTreeNode
,
int
>
>&
temps
)
{
if
(
findTempIndex
(
node
,
temps
)
!=
-
1
)
return
;
// We have already processed a node identical to this one.
// Process the child nodes.
vector
<
int
>
args
;
for
(
int
i
=
0
;
i
<
node
.
getChildren
().
size
();
i
++
)
{
compileExpression
(
node
.
getChildren
()[
i
],
temps
);
args
.
push_back
(
findTempIndex
(
node
.
getChildren
()[
i
],
temps
));
}
// Process this node.
if
(
node
.
getOperation
().
getId
()
==
Operation
::
VARIABLE
)
{
variableIndices
[
node
.
getOperation
().
getName
()]
=
(
int
)
workspace
.
size
();
variableNames
.
insert
(
node
.
getOperation
().
getName
());
}
else
{
int
stepIndex
=
(
int
)
arguments
.
size
();
arguments
.
push_back
(
vector
<
int
>
());
target
.
push_back
((
int
)
workspace
.
size
());
operation
.
push_back
(
node
.
getOperation
().
clone
());
if
(
args
.
size
()
==
0
)
arguments
[
stepIndex
].
push_back
(
0
);
// The value won't actually be used. We just need something there.
else
{
// If the arguments are sequential, we can just pass a pointer to the first one.
bool
sequential
=
true
;
for
(
int
i
=
1
;
i
<
args
.
size
();
i
++
)
if
(
args
[
i
]
!=
args
[
i
-
1
]
+
1
)
sequential
=
false
;
if
(
sequential
)
arguments
[
stepIndex
].
push_back
(
args
[
0
]);
else
arguments
[
stepIndex
]
=
args
;
}
}
temps
.
push_back
(
make_pair
(
node
,
workspace
.
size
()));
workspace
.
push_back
(
0.0
);
}
int
CompiledExpression
::
findTempIndex
(
const
ExpressionTreeNode
&
node
,
vector
<
pair
<
ExpressionTreeNode
,
int
>
>&
temps
)
{
for
(
int
i
=
0
;
i
<
(
int
)
temps
.
size
();
i
++
)
if
(
temps
[
i
].
first
==
node
)
return
i
;
return
-
1
;
}
const
set
<
string
>&
CompiledExpression
::
getVariables
()
const
{
return
variableNames
;
}
double
&
CompiledExpression
::
getVariableReference
(
const
string
&
name
)
{
map
<
string
,
int
>::
iterator
index
=
variableIndices
.
find
(
name
);
if
(
index
==
variableIndices
.
end
())
throw
Exception
(
"getVariableReference: Unknown variable '"
+
name
+
"'"
);
return
workspace
[
index
->
second
];
}
double
CompiledExpression
::
evaluate
()
const
{
#ifdef LEPTON_USE_JIT
return
((
double
(
*
)())
jitCode
)();
#else
// Loop over the operations and evaluate each one.
for
(
int
step
=
0
;
step
<
operation
.
size
();
step
++
)
{
const
vector
<
int
>&
args
=
arguments
[
step
];
if
(
args
.
size
()
==
1
)
workspace
[
target
[
step
]]
=
operation
[
step
]
->
evaluate
(
&
workspace
[
args
[
0
]],
dummyVariables
);
else
{
for
(
int
i
=
0
;
i
<
args
.
size
();
i
++
)
argValues
[
i
]
=
workspace
[
args
[
i
]];
workspace
[
target
[
step
]]
=
operation
[
step
]
->
evaluate
(
&
argValues
[
0
],
dummyVariables
);
}
}
return
workspace
[
workspace
.
size
()
-
1
];
#endif
}
#ifdef LEPTON_USE_JIT
static
double
evaluateOperation
(
Operation
*
op
,
double
*
args
)
{
map
<
string
,
double
>*
dummyVariables
=
NULL
;
return
op
->
evaluate
(
args
,
*
dummyVariables
);
}
void
CompiledExpression
::
generateJitCode
()
{
X86Compiler
c
(
&
runtime
);
c
.
addFunc
(
kFuncConvHost
,
FuncBuilder0
<
double
>
());
vector
<
X86XmmVar
>
workspaceVar
(
workspace
.
size
());
for
(
int
i
=
0
;
i
<
(
int
)
workspaceVar
.
size
();
i
++
)
workspaceVar
[
i
]
=
c
.
newXmmVar
(
kX86VarTypeXmmSd
);
X86GpVar
workspacePointer
(
c
);
X86GpVar
argsPointer
(
c
);
c
.
mov
(
workspacePointer
,
imm_ptr
(
&
workspace
[
0
]));
c
.
mov
(
argsPointer
,
imm_ptr
(
&
argValues
[
0
]));
// Load the arguments into variables.
for
(
set
<
string
>::
const_iterator
iter
=
variableNames
.
begin
();
iter
!=
variableNames
.
end
();
++
iter
)
{
map
<
string
,
int
>::
iterator
index
=
variableIndices
.
find
(
*
iter
);
c
.
movsd
(
workspaceVar
[
index
->
second
],
x86
::
ptr
(
workspacePointer
,
8
*
index
->
second
,
0
));
}
// Make a list of all constants that will be needed for evaluation.
vector
<
int
>
operationConstantIndex
(
operation
.
size
(),
-
1
);
for
(
int
step
=
0
;
step
<
(
int
)
operation
.
size
();
step
++
)
{
// Find the constant value (if any) used by this operation.
Operation
&
op
=
*
operation
[
step
];
double
value
;
if
(
op
.
getId
()
==
Operation
::
CONSTANT
)
value
=
dynamic_cast
<
Operation
::
Constant
&>
(
op
).
getValue
();
else
if
(
op
.
getId
()
==
Operation
::
ADD_CONSTANT
)
value
=
dynamic_cast
<
Operation
::
AddConstant
&>
(
op
).
getValue
();
else
if
(
op
.
getId
()
==
Operation
::
MULTIPLY_CONSTANT
)
value
=
dynamic_cast
<
Operation
::
MultiplyConstant
&>
(
op
).
getValue
();
else
if
(
op
.
getId
()
==
Operation
::
RECIPROCAL
)
value
=
1.0
;
else
if
(
op
.
getId
()
==
Operation
::
STEP
)
value
=
1.0
;
else
if
(
op
.
getId
()
==
Operation
::
DELTA
)
value
=
1.0
;
else
continue
;
// See if we already have a variable for this constant.
for
(
int
i
=
0
;
i
<
(
int
)
constants
.
size
();
i
++
)
if
(
value
==
constants
[
i
])
{
operationConstantIndex
[
step
]
=
i
;
break
;
}
if
(
operationConstantIndex
[
step
]
==
-
1
)
{
operationConstantIndex
[
step
]
=
constants
.
size
();
constants
.
push_back
(
value
);
}
}
// Load constants into variables.
vector
<
X86XmmVar
>
constantVar
(
constants
.
size
());
if
(
constants
.
size
()
>
0
)
{
X86GpVar
constantsPointer
(
c
);
c
.
mov
(
constantsPointer
,
imm_ptr
(
&
constants
[
0
]));
for
(
int
i
=
0
;
i
<
(
int
)
constants
.
size
();
i
++
)
{
constantVar
[
i
]
=
c
.
newXmmVar
(
kX86VarTypeXmmSd
);
c
.
movsd
(
constantVar
[
i
],
x86
::
ptr
(
constantsPointer
,
8
*
i
,
0
));
}
}
// Evaluate the operations.
for
(
int
step
=
0
;
step
<
(
int
)
operation
.
size
();
step
++
)
{
Operation
&
op
=
*
operation
[
step
];
vector
<
int
>
args
=
arguments
[
step
];
if
(
args
.
size
()
==
1
)
{
// One or more sequential arguments. Fill out the list.
for
(
int
i
=
1
;
i
<
op
.
getNumArguments
();
i
++
)
args
.
push_back
(
args
[
0
]
+
i
);
}
// Generate instructions to execute this operation.
switch
(
op
.
getId
())
{
case
Operation
::
CONSTANT
:
c
.
movsd
(
workspaceVar
[
target
[
step
]],
constantVar
[
operationConstantIndex
[
step
]]);
break
;
case
Operation
::
ADD
:
c
.
movsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
c
.
addsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
1
]]);
break
;
case
Operation
::
SUBTRACT
:
c
.
movsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
c
.
subsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
1
]]);
break
;
case
Operation
::
MULTIPLY
:
c
.
movsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
c
.
mulsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
1
]]);
break
;
case
Operation
::
DIVIDE
:
c
.
movsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
c
.
divsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
1
]]);
break
;
case
Operation
::
NEGATE
:
c
.
xorps
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
target
[
step
]]);
c
.
subsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
break
;
case
Operation
::
SQRT
:
c
.
sqrtsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
break
;
case
Operation
::
EXP
:
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
exp
);
break
;
case
Operation
::
LOG
:
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
log
);
break
;
case
Operation
::
SIN
:
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
sin
);
break
;
case
Operation
::
COS
:
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
cos
);
break
;
case
Operation
::
TAN
:
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
tan
);
break
;
case
Operation
::
ASIN
:
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
asin
);
break
;
case
Operation
::
ACOS
:
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
acos
);
break
;
case
Operation
::
ATAN
:
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
atan
);
break
;
case
Operation
::
SINH
:
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
sinh
);
break
;
case
Operation
::
COSH
:
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
cosh
);
break
;
case
Operation
::
TANH
:
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
tanh
);
break
;
case
Operation
::
STEP
:
c
.
xorps
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
target
[
step
]]);
c
.
cmpsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
imm
(
18
));
// Comparison mode is _CMP_LE_OQ = 18
c
.
andps
(
workspaceVar
[
target
[
step
]],
constantVar
[
operationConstantIndex
[
step
]]);
break
;
case
Operation
::
DELTA
:
c
.
xorps
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
target
[
step
]]);
c
.
cmpsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
imm
(
16
));
// Comparison mode is _CMP_EQ_OS = 16
c
.
andps
(
workspaceVar
[
target
[
step
]],
constantVar
[
operationConstantIndex
[
step
]]);
break
;
case
Operation
::
SQUARE
:
c
.
movsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
c
.
mulsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
break
;
case
Operation
::
CUBE
:
c
.
movsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
c
.
mulsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
c
.
mulsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
break
;
case
Operation
::
RECIPROCAL
:
c
.
movsd
(
workspaceVar
[
target
[
step
]],
constantVar
[
operationConstantIndex
[
step
]]);
c
.
divsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
break
;
case
Operation
::
ADD_CONSTANT
:
c
.
movsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
c
.
addsd
(
workspaceVar
[
target
[
step
]],
constantVar
[
operationConstantIndex
[
step
]]);
break
;
case
Operation
::
MULTIPLY_CONSTANT
:
c
.
movsd
(
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]]);
c
.
mulsd
(
workspaceVar
[
target
[
step
]],
constantVar
[
operationConstantIndex
[
step
]]);
break
;
case
Operation
::
ABS
:
generateSingleArgCall
(
c
,
workspaceVar
[
target
[
step
]],
workspaceVar
[
args
[
0
]],
fabs
);
break
;
default:
// Just invoke evaluateOperation().
for
(
int
i
=
0
;
i
<
(
int
)
args
.
size
();
i
++
)
c
.
movsd
(
x86
::
ptr
(
argsPointer
,
8
*
i
,
0
),
workspaceVar
[
args
[
i
]]);
X86GpVar
fn
(
c
,
kVarTypeIntPtr
);
c
.
mov
(
fn
,
imm_ptr
((
void
*
)
evaluateOperation
));
X86CallNode
*
call
=
c
.
call
(
fn
,
kFuncConvHost
,
FuncBuilder2
<
double
,
Operation
*
,
double
*>
());
call
->
setArg
(
0
,
imm_ptr
(
&
op
));
call
->
setArg
(
1
,
imm_ptr
(
&
argValues
[
0
]));
call
->
setRet
(
0
,
workspaceVar
[
target
[
step
]]);
}
}
c
.
ret
(
workspaceVar
[
workspace
.
size
()
-
1
]);
c
.
endFunc
();
jitCode
=
c
.
make
();
}
void
CompiledExpression
::
generateSingleArgCall
(
X86Compiler
&
c
,
X86XmmVar
&
dest
,
X86XmmVar
&
arg
,
double
(
*
function
)(
double
))
{
X86GpVar
fn
(
c
,
kVarTypeIntPtr
);
c
.
mov
(
fn
,
imm_ptr
((
void
*
)
function
));
X86CallNode
*
call
=
c
.
call
(
fn
,
kFuncConvHost
,
FuncBuilder1
<
double
,
double
>
());
call
->
setArg
(
0
,
arg
);
call
->
setRet
(
0
,
dest
);
}
#endif
\ No newline at end of file
tests/TestParser.cpp
View file @
751ff079
...
...
@@ -127,6 +127,18 @@ void verifyInvalidExpression(const string& expression) {
throw
exception
();
}
/**
* Verify that two numbers have the same value.
*/
void
assertNumbersEqual
(
double
val1
,
double
val2
)
{
const
double
inf
=
numeric_limits
<
double
>::
infinity
();
if
(
val1
==
val1
||
val2
==
val2
)
// If both are NaN, that's fine.
if
(
val1
!=
inf
||
val2
!=
inf
)
// Both infinity is also fine.
if
(
val1
!=
-
inf
||
val2
!=
-
inf
)
// Same for -infinity.
ASSERT_EQUAL_TOL
(
val1
,
val2
,
1e-10
);
}
/**
* Verify that two expressions give the same value.
*/
...
...
@@ -137,11 +149,22 @@ void verifySameValue(const ParsedExpression& exp1, const ParsedExpression& exp2,
variables
[
"y"
]
=
y
;
double
val1
=
exp1
.
evaluate
(
variables
);
double
val2
=
exp2
.
evaluate
(
variables
);
const
double
inf
=
numeric_limits
<
double
>::
infinity
();
if
(
val1
==
val1
||
val2
==
val2
)
// If both are NaN, that's fine.
if
(
val1
!=
inf
||
val2
!=
inf
)
// Both infinity is also fine.
if
(
val1
!=
-
inf
||
val2
!=
-
inf
)
// Same for -infinity.
ASSERT_EQUAL_TOL
(
val1
,
val2
,
1e-10
);
assertNumbersEqual
(
val1
,
val2
);
// Now create CompiledExpressions from them and see if those also match.
CompiledExpression
compiled1
=
exp1
.
createCompiledExpression
();
CompiledExpression
compiled2
=
exp2
.
createCompiledExpression
();
if
(
compiled1
.
getVariables
().
find
(
"x"
)
!=
compiled1
.
getVariables
().
end
())
compiled1
.
getVariableReference
(
"x"
)
=
x
;
if
(
compiled1
.
getVariables
().
find
(
"y"
)
!=
compiled1
.
getVariables
().
end
())
compiled1
.
getVariableReference
(
"y"
)
=
y
;
if
(
compiled2
.
getVariables
().
find
(
"x"
)
!=
compiled2
.
getVariables
().
end
())
compiled2
.
getVariableReference
(
"x"
)
=
x
;
if
(
compiled2
.
getVariables
().
find
(
"y"
)
!=
compiled2
.
getVariables
().
end
())
compiled2
.
getVariableReference
(
"y"
)
=
y
;
assertNumbersEqual
(
val1
,
compiled1
.
evaluate
());
assertNumbersEqual
(
val2
,
compiled2
.
evaluate
());
}
/**
...
...
@@ -171,14 +194,14 @@ void testCustomFunction(const string& expression, const string& equivalent) {
verifySameValue
(
exp1
,
exp2
,
2.0
,
3.0
);
verifySameValue
(
exp1
,
exp2
,
-
2.0
,
3.0
);
verifySameValue
(
exp1
,
exp2
,
2.0
,
-
3.0
);
ParsedExpression
deriv1
=
exp1
.
differentiate
(
"x"
);
ParsedExpression
deriv2
=
exp2
.
differentiate
(
"x"
);
ParsedExpression
deriv1
=
exp1
.
differentiate
(
"x"
)
.
optimize
()
;
ParsedExpression
deriv2
=
exp2
.
differentiate
(
"x"
)
.
optimize
()
;
verifySameValue
(
deriv1
,
deriv2
,
1.0
,
2.0
);
verifySameValue
(
deriv1
,
deriv2
,
2.0
,
3.0
);
verifySameValue
(
deriv1
,
deriv2
,
-
2.0
,
3.0
);
verifySameValue
(
deriv1
,
deriv2
,
2.0
,
-
3.0
);
ParsedExpression
deriv3
=
deriv1
.
differentiate
(
"y"
);
ParsedExpression
deriv4
=
deriv2
.
differentiate
(
"y"
);
ParsedExpression
deriv3
=
deriv1
.
differentiate
(
"y"
)
.
optimize
()
;
ParsedExpression
deriv4
=
deriv2
.
differentiate
(
"y"
)
.
optimize
()
;
verifySameValue
(
deriv3
,
deriv4
,
1.0
,
2.0
);
verifySameValue
(
deriv3
,
deriv4
,
2.0
,
3.0
);
verifySameValue
(
deriv3
,
deriv4
,
-
2.0
,
3.0
);
...
...
@@ -223,6 +246,7 @@ int main() {
verifyEvaluation
(
"max(x, -1)"
,
2.0
,
3.0
,
2.0
);
verifyEvaluation
(
"abs(x-y)"
,
2.0
,
3.0
,
1.0
);
verifyEvaluation
(
"delta(x)+3*delta(y-1.5)"
,
2.0
,
1.5
,
3.0
);
verifyEvaluation
(
"step(x-3)+y*step(x)"
,
2.0
,
3.0
,
3.0
);
verifyInvalidExpression
(
"1..2"
);
verifyInvalidExpression
(
"1*(2+3"
);
verifyInvalidExpression
(
"5++4"
);
...
...
Prev
1
2
3
4
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