mirror of
https://github.com/asmjit/asmjit.git
synced 2025-12-17 12:34:35 +03:00
Added ASMJIT_NOEXCEPT macro
Replaced some inlined ASSERTs by runtime checks in X86Assembler.
This commit is contained in:
@@ -669,6 +669,16 @@
|
|||||||
#endif
|
#endif
|
||||||
// [@CC_REGPARM}@]
|
// [@CC_REGPARM}@]
|
||||||
|
|
||||||
|
// [@CC_NOEXCEPT{@]
|
||||||
|
// \def ASMJIT_NOEXCEPT
|
||||||
|
// The decorated function never throws an exception (noexcept).
|
||||||
|
#if ASMJIT_HAS_NOEXCEPT
|
||||||
|
# define ASMJIT_NOEXCEPT noexcept
|
||||||
|
#else
|
||||||
|
# define ASMJIT_NOEXCEPT
|
||||||
|
#endif
|
||||||
|
// [@CC_NOEXCEPT}@]
|
||||||
|
|
||||||
// [@CC_NOP{@]
|
// [@CC_NOP{@]
|
||||||
// \def ASMJIT_NOP
|
// \def ASMJIT_NOP
|
||||||
// No operation.
|
// No operation.
|
||||||
|
|||||||
@@ -1111,7 +1111,8 @@ static ASMJIT_INLINE Error X86Assembler_emit(Assembler* self_, uint32_t code, co
|
|||||||
ADD_REX_W_BY_SIZE(o0->getSize());
|
ADD_REX_W_BY_SIZE(o0->getSize());
|
||||||
|
|
||||||
if (encoded == ENC_OPS(Reg, Reg, None)) {
|
if (encoded == ENC_OPS(Reg, Reg, None)) {
|
||||||
ASMJIT_ASSERT(o0->getSize() != 1);
|
if (o0->getSize() == 1 || o0->getSize() != o1->getSize())
|
||||||
|
goto _IllegalInst;
|
||||||
|
|
||||||
opReg = x86OpReg(o0);
|
opReg = x86OpReg(o0);
|
||||||
rmReg = x86OpReg(o1);
|
rmReg = x86OpReg(o1);
|
||||||
@@ -1119,7 +1120,8 @@ static ASMJIT_INLINE Error X86Assembler_emit(Assembler* self_, uint32_t code, co
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (encoded == ENC_OPS(Reg, Mem, None)) {
|
if (encoded == ENC_OPS(Reg, Mem, None)) {
|
||||||
ASMJIT_ASSERT(o0->getSize() != 1);
|
if (o0->getSize() == 1)
|
||||||
|
goto _IllegalInst;
|
||||||
|
|
||||||
opReg = x86OpReg(o0);
|
opReg = x86OpReg(o0);
|
||||||
rmMem = x86OpMem(o1);
|
rmMem = x86OpMem(o1);
|
||||||
@@ -1208,6 +1210,9 @@ static ASMJIT_INLINE Error X86Assembler_emit(Assembler* self_, uint32_t code, co
|
|||||||
|
|
||||||
case kX86InstEncodingIdX86BSwap:
|
case kX86InstEncodingIdX86BSwap:
|
||||||
if (encoded == ENC_OPS(Reg, None, None)) {
|
if (encoded == ENC_OPS(Reg, None, None)) {
|
||||||
|
if (o0->getSize() < 4)
|
||||||
|
goto _IllegalInst;
|
||||||
|
|
||||||
opReg = x86OpReg(o0);
|
opReg = x86OpReg(o0);
|
||||||
ADD_REX_W_BY_SIZE(o0->getSize());
|
ADD_REX_W_BY_SIZE(o0->getSize());
|
||||||
goto _EmitX86OpWithOpReg;
|
goto _EmitX86OpWithOpReg;
|
||||||
@@ -1505,7 +1510,8 @@ static ASMJIT_INLINE Error X86Assembler_emit(Assembler* self_, uint32_t code, co
|
|||||||
|
|
||||||
case kX86InstEncodingIdX86Jecxz:
|
case kX86InstEncodingIdX86Jecxz:
|
||||||
if (encoded == ENC_OPS(Reg, Label, None)) {
|
if (encoded == ENC_OPS(Reg, Label, None)) {
|
||||||
ASMJIT_ASSERT(x86OpReg(o0) == kX86RegIndexCx);
|
if (x86OpReg(o0) != kX86RegIndexCx)
|
||||||
|
goto _IllegalInst;
|
||||||
|
|
||||||
if ((Arch == kArchX86 && o0->getSize() == 2) ||
|
if ((Arch == kArchX86 && o0->getSize() == 2) ||
|
||||||
(Arch == kArchX64 && o0->getSize() == 4)) {
|
(Arch == kArchX64 && o0->getSize() == 4)) {
|
||||||
@@ -1797,7 +1803,8 @@ static ASMJIT_INLINE Error X86Assembler_emit(Assembler* self_, uint32_t code, co
|
|||||||
|
|
||||||
case kX86InstEncodingIdX86MovPtr:
|
case kX86InstEncodingIdX86MovPtr:
|
||||||
if (encoded == ENC_OPS(Reg, Imm, None)) {
|
if (encoded == ENC_OPS(Reg, Imm, None)) {
|
||||||
ASMJIT_ASSERT(x86OpReg(o0) == 0);
|
if (x86OpReg(o0) != 0)
|
||||||
|
goto _IllegalInst;
|
||||||
|
|
||||||
opCode += o0->getSize() != 1;
|
opCode += o0->getSize() != 1;
|
||||||
ADD_66H_P_BY_SIZE(o0->getSize());
|
ADD_66H_P_BY_SIZE(o0->getSize());
|
||||||
@@ -1812,7 +1819,8 @@ static ASMJIT_INLINE Error X86Assembler_emit(Assembler* self_, uint32_t code, co
|
|||||||
opCode = extendedInfo.getSecondaryOpCode();
|
opCode = extendedInfo.getSecondaryOpCode();
|
||||||
|
|
||||||
if (encoded == ENC_OPS(Imm, Reg, None)) {
|
if (encoded == ENC_OPS(Imm, Reg, None)) {
|
||||||
ASMJIT_ASSERT(x86OpReg(o1) == 0);
|
if (x86OpReg(o1) != 0)
|
||||||
|
goto _IllegalInst;
|
||||||
|
|
||||||
opCode += o1->getSize() != 1;
|
opCode += o1->getSize() != 1;
|
||||||
ADD_66H_P_BY_SIZE(o1->getSize());
|
ADD_66H_P_BY_SIZE(o1->getSize());
|
||||||
@@ -1828,7 +1836,8 @@ static ASMJIT_INLINE Error X86Assembler_emit(Assembler* self_, uint32_t code, co
|
|||||||
if (encoded == ENC_OPS(Reg, None, None)) {
|
if (encoded == ENC_OPS(Reg, None, None)) {
|
||||||
if (o0->isRegType(kX86RegTypeSeg)) {
|
if (o0->isRegType(kX86RegTypeSeg)) {
|
||||||
uint32_t segment = x86OpReg(o0);
|
uint32_t segment = x86OpReg(o0);
|
||||||
ASMJIT_ASSERT(segment < kX86SegCount);
|
if (segment >= kX86SegCount)
|
||||||
|
goto _IllegalInst;
|
||||||
|
|
||||||
if (segment >= kX86SegFs)
|
if (segment >= kX86SegFs)
|
||||||
EMIT_BYTE(0x0F);
|
EMIT_BYTE(0x0F);
|
||||||
@@ -1854,7 +1863,8 @@ static ASMJIT_INLINE Error X86Assembler_emit(Assembler* self_, uint32_t code, co
|
|||||||
if (encoded == ENC_OPS(Reg, None, None)) {
|
if (encoded == ENC_OPS(Reg, None, None)) {
|
||||||
if (o0->isRegType(kX86RegTypeSeg)) {
|
if (o0->isRegType(kX86RegTypeSeg)) {
|
||||||
uint32_t segment = x86OpReg(o0);
|
uint32_t segment = x86OpReg(o0);
|
||||||
ASMJIT_ASSERT(segment < kX86SegCount);
|
if (segment == kX86SegCs || segment >= kX86SegCount)
|
||||||
|
goto _IllegalInst;
|
||||||
|
|
||||||
if (segment >= kX86SegFs)
|
if (segment >= kX86SegFs)
|
||||||
EMIT_BYTE(0x0F);
|
EMIT_BYTE(0x0F);
|
||||||
@@ -1864,8 +1874,11 @@ static ASMJIT_INLINE Error X86Assembler_emit(Assembler* self_, uint32_t code, co
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
_GroupPop_Gp:
|
_GroupPop_Gp:
|
||||||
ASMJIT_ASSERT(static_cast<const X86Reg*>(o0)->getSize() == 2 ||
|
// We allow 2 byte, 4 byte, and 8 byte register sizes, althought PUSH
|
||||||
static_cast<const X86Reg*>(o0)->getSize() == self->_regSize);
|
// and POP only allows 2 bytes or register width. On 64-bit we simply
|
||||||
|
// PUSH/POP 64-bit register even if 32-bit register was given.
|
||||||
|
if (o0->getSize() < 1)
|
||||||
|
goto _IllegalInst;
|
||||||
|
|
||||||
opCode = extendedInfo.getSecondaryOpCode();
|
opCode = extendedInfo.getSecondaryOpCode();
|
||||||
opReg = x86OpReg(o0);
|
opReg = x86OpReg(o0);
|
||||||
@@ -1876,8 +1889,10 @@ _GroupPop_Gp:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (encoded == ENC_OPS(Mem, None, None)) {
|
if (encoded == ENC_OPS(Mem, None, None)) {
|
||||||
ADD_66H_P_BY_SIZE(o0->getSize());
|
if (o0->getSize() != 2 && o0->getSize() != 8)
|
||||||
|
goto _IllegalInst;
|
||||||
|
|
||||||
|
ADD_66H_P_BY_SIZE(o0->getSize());
|
||||||
rmMem = x86OpMem(o0);
|
rmMem = x86OpMem(o0);
|
||||||
goto _EmitX86M;
|
goto _EmitX86M;
|
||||||
}
|
}
|
||||||
@@ -2142,10 +2157,13 @@ _EmitFpArith_Reg:
|
|||||||
opCode = 0xD800 + ((opCode >> 8) & 0xFF) + static_cast<uint32_t>(rmReg);
|
opCode = 0xD800 + ((opCode >> 8) & 0xFF) + static_cast<uint32_t>(rmReg);
|
||||||
goto _EmitFpuOp;
|
goto _EmitFpuOp;
|
||||||
}
|
}
|
||||||
else {
|
else if (rmReg == 0) {
|
||||||
opCode = 0xDC00 + ((opCode >> 0) & 0xFF) + static_cast<uint32_t>(rmReg);
|
opCode = 0xDC00 + ((opCode >> 0) & 0xFF) + static_cast<uint32_t>(rmReg);
|
||||||
goto _EmitFpuOp;
|
goto _EmitFpuOp;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
goto _IllegalInst;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (encoded == ENC_OPS(Mem, None, None)) {
|
if (encoded == ENC_OPS(Mem, None, None)) {
|
||||||
@@ -2272,8 +2290,8 @@ _EmitFpArith_Mem:
|
|||||||
ADD_REX_W_BY_SIZE(o0->getSize());
|
ADD_REX_W_BY_SIZE(o0->getSize());
|
||||||
|
|
||||||
if (encoded == ENC_OPS(Reg, Reg, None)) {
|
if (encoded == ENC_OPS(Reg, Reg, None)) {
|
||||||
ASMJIT_ASSERT(static_cast<const Reg*>(o0)->getRegType() == kX86RegTypeGpd ||
|
if (!Utils::inInterval<uint32_t>(static_cast<const X86Reg*>(o0)->getRegType(), kX86RegTypeGpd, kX86RegTypeGpq))
|
||||||
static_cast<const Reg*>(o0)->getRegType() == kX86RegTypeGpq);
|
goto _IllegalInst;
|
||||||
|
|
||||||
opCode += o0->getSize() != 1;
|
opCode += o0->getSize() != 1;
|
||||||
opReg = x86OpReg(o0);
|
opReg = x86OpReg(o0);
|
||||||
@@ -2282,8 +2300,8 @@ _EmitFpArith_Mem:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (encoded == ENC_OPS(Reg, Mem, None)) {
|
if (encoded == ENC_OPS(Reg, Mem, None)) {
|
||||||
ASMJIT_ASSERT(static_cast<const Reg*>(o0)->getRegType() == kX86RegTypeGpd ||
|
if (!Utils::inInterval<uint32_t>(static_cast<const X86Reg*>(o0)->getRegType(), kX86RegTypeGpd, kX86RegTypeGpq))
|
||||||
static_cast<const Reg*>(o0)->getRegType() == kX86RegTypeGpq);
|
goto _IllegalInst;
|
||||||
|
|
||||||
opCode += o0->getSize() != 1;
|
opCode += o0->getSize() != 1;
|
||||||
opReg = x86OpReg(o0);
|
opReg = x86OpReg(o0);
|
||||||
@@ -2403,6 +2421,9 @@ _EmitFpArith_Mem:
|
|||||||
|
|
||||||
case kX86InstEncodingIdExtMovBe:
|
case kX86InstEncodingIdExtMovBe:
|
||||||
if (encoded == ENC_OPS(Reg, Mem, None)) {
|
if (encoded == ENC_OPS(Reg, Mem, None)) {
|
||||||
|
if (o0->getSize() == 1)
|
||||||
|
goto _IllegalInst;
|
||||||
|
|
||||||
ADD_66H_P_BY_SIZE(o0->getSize());
|
ADD_66H_P_BY_SIZE(o0->getSize());
|
||||||
ADD_REX_W_BY_SIZE(o0->getSize());
|
ADD_REX_W_BY_SIZE(o0->getSize());
|
||||||
|
|
||||||
@@ -2415,6 +2436,9 @@ _EmitFpArith_Mem:
|
|||||||
opCode = extendedInfo.getSecondaryOpCode();
|
opCode = extendedInfo.getSecondaryOpCode();
|
||||||
|
|
||||||
if (encoded == ENC_OPS(Mem, Reg, None)) {
|
if (encoded == ENC_OPS(Mem, Reg, None)) {
|
||||||
|
if (o1->getSize() == 1)
|
||||||
|
goto _IllegalInst;
|
||||||
|
|
||||||
ADD_66H_P_BY_SIZE(o1->getSize());
|
ADD_66H_P_BY_SIZE(o1->getSize());
|
||||||
ADD_REX_W_BY_SIZE(o1->getSize());
|
ADD_REX_W_BY_SIZE(o1->getSize());
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
namespace asmjit {
|
namespace asmjit {
|
||||||
|
|
||||||
//! \addtogroup asmjit_x86_general
|
//! \addtogroup asmjit_x86
|
||||||
//! \{
|
//! \{
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -28,91 +28,91 @@ namespace asmjit {
|
|||||||
// \internal
|
// \internal
|
||||||
#define ASMJIT_X86_EMIT_OPTIONS(T) \
|
#define ASMJIT_X86_EMIT_OPTIONS(T) \
|
||||||
/*! Force short form of jmp/jcc instruction. */ \
|
/*! Force short form of jmp/jcc instruction. */ \
|
||||||
ASMJIT_INLINE T& short_() { \
|
ASMJIT_INLINE T& short_() noexcept { \
|
||||||
_instOptions |= kInstOptionShortForm; \
|
_instOptions |= kInstOptionShortForm; \
|
||||||
return *this; \
|
return *this; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/*! Force long form of jmp/jcc instruction. */ \
|
/*! Force long form of jmp/jcc instruction. */ \
|
||||||
ASMJIT_INLINE T& long_() { \
|
ASMJIT_INLINE T& long_() noexcept { \
|
||||||
_instOptions |= kInstOptionLongForm; \
|
_instOptions |= kInstOptionLongForm; \
|
||||||
return *this; \
|
return *this; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/*! Condition is likely to be taken (has only benefit on P4). */ \
|
/*! Condition is likely to be taken (has only benefit on P4). */ \
|
||||||
ASMJIT_INLINE T& taken() { \
|
ASMJIT_INLINE T& taken() noexcept { \
|
||||||
_instOptions |= kInstOptionTaken; \
|
_instOptions |= kInstOptionTaken; \
|
||||||
return *this; \
|
return *this; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/*! Condition is unlikely to be taken (has only benefit on P4). */ \
|
/*! Condition is unlikely to be taken (has only benefit on P4). */ \
|
||||||
ASMJIT_INLINE T& notTaken() { \
|
ASMJIT_INLINE T& notTaken() noexcept { \
|
||||||
_instOptions |= kInstOptionNotTaken; \
|
_instOptions |= kInstOptionNotTaken; \
|
||||||
return *this; \
|
return *this; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/*! Use LOCK prefix. */ \
|
/*! Use LOCK prefix. */ \
|
||||||
ASMJIT_INLINE T& lock() { \
|
ASMJIT_INLINE T& lock() noexcept { \
|
||||||
_instOptions |= kX86InstOptionLock; \
|
_instOptions |= kX86InstOptionLock; \
|
||||||
return *this; \
|
return *this; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/*! Force REX prefix (X64). */ \
|
/*! Force REX prefix (X64). */ \
|
||||||
ASMJIT_INLINE T& rex() { \
|
ASMJIT_INLINE T& rex() noexcept { \
|
||||||
_instOptions |= kX86InstOptionRex; \
|
_instOptions |= kX86InstOptionRex; \
|
||||||
return *this; \
|
return *this; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/*! Force 3-byte VEX prefix (AVX+). */ \
|
/*! Force 3-byte VEX prefix (AVX+). */ \
|
||||||
ASMJIT_INLINE T& vex3() { \
|
ASMJIT_INLINE T& vex3() noexcept { \
|
||||||
_instOptions |= kX86InstOptionVex3; \
|
_instOptions |= kX86InstOptionVex3; \
|
||||||
return *this; \
|
return *this; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/*! Force 4-byte EVEX prefix (AVX512+). */ \
|
/*! Force 4-byte EVEX prefix (AVX512+). */ \
|
||||||
ASMJIT_INLINE T& evex() { \
|
ASMJIT_INLINE T& evex() noexcept { \
|
||||||
_instOptions |= kX86InstOptionEvex; \
|
_instOptions |= kX86InstOptionEvex; \
|
||||||
return *this; \
|
return *this; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/*! Use zeroing instead of merging (AVX512+). */ \
|
/*! Use zeroing instead of merging (AVX512+). */ \
|
||||||
ASMJIT_INLINE T& z() { \
|
ASMJIT_INLINE T& z() noexcept { \
|
||||||
_instOptions |= kX86InstOptionEvexZero; \
|
_instOptions |= kX86InstOptionEvexZero; \
|
||||||
return *this; \
|
return *this; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/*! Broadcast one element to all other elements (AVX512+). */ \
|
/*! Broadcast one element to all other elements (AVX512+). */ \
|
||||||
ASMJIT_INLINE T& _1ToN() { \
|
ASMJIT_INLINE T& _1ToN() noexcept { \
|
||||||
_instOptions |= kX86InstOptionEvexOneN; \
|
_instOptions |= kX86InstOptionEvexOneN; \
|
||||||
return *this; \
|
return *this; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/*! Suppress all exceptions (AVX512+). */ \
|
/*! Suppress all exceptions (AVX512+). */ \
|
||||||
ASMJIT_INLINE T& sae() { \
|
ASMJIT_INLINE T& sae() noexcept { \
|
||||||
_instOptions |= kX86InstOptionEvexSae; \
|
_instOptions |= kX86InstOptionEvexSae; \
|
||||||
return *this; \
|
return *this; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/*! Static rounding mode `round-to-nearest` (even) and `SAE` (AVX512+). */ \
|
/*! Static rounding mode `round-to-nearest` (even) and `SAE` (AVX512+). */ \
|
||||||
ASMJIT_INLINE T& rn_sae() { \
|
ASMJIT_INLINE T& rn_sae() noexcept { \
|
||||||
_instOptions |= kX86InstOptionEvexRnSae; \
|
_instOptions |= kX86InstOptionEvexRnSae; \
|
||||||
return *this; \
|
return *this; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/*! Static rounding mode `round-down` (toward -inf) and `SAE` (AVX512+). */ \
|
/*! Static rounding mode `round-down` (toward -inf) and `SAE` (AVX512+). */ \
|
||||||
ASMJIT_INLINE T& rd_sae() { \
|
ASMJIT_INLINE T& rd_sae() noexcept { \
|
||||||
_instOptions |= kX86InstOptionEvexRdSae; \
|
_instOptions |= kX86InstOptionEvexRdSae; \
|
||||||
return *this; \
|
return *this; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/*! Static rounding mode `round-up` (toward +inf) and `SAE` (AVX512+). */ \
|
/*! Static rounding mode `round-up` (toward +inf) and `SAE` (AVX512+). */ \
|
||||||
ASMJIT_INLINE T& ru_sae() { \
|
ASMJIT_INLINE T& ru_sae() noexcept { \
|
||||||
_instOptions |= kX86InstOptionEvexRuSae; \
|
_instOptions |= kX86InstOptionEvexRuSae; \
|
||||||
return *this; \
|
return *this; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/*! Static rounding mode `round-toward-zero` (truncate) and `SAE` (AVX512+). */ \
|
/*! Static rounding mode `round-toward-zero` (truncate) and `SAE` (AVX512+). */ \
|
||||||
ASMJIT_INLINE T& rz_sae() { \
|
ASMJIT_INLINE T& rz_sae() noexcept { \
|
||||||
_instOptions |= kX86InstOptionEvexRzSae; \
|
_instOptions |= kX86InstOptionEvexRzSae; \
|
||||||
return *this; \
|
return *this; \
|
||||||
}
|
}
|
||||||
@@ -549,12 +549,6 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
|
|||||||
return emit(_Code_, o0); \
|
return emit(_Code_, o0); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INST_1x_(_Inst_, _Code_, _Op0_, _Cond_) \
|
|
||||||
ASMJIT_INLINE Error _Inst_(const _Op0_& o0) { \
|
|
||||||
ASMJIT_ASSERT(_Cond_); \
|
|
||||||
return emit(_Code_, o0); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define INST_1i(_Inst_, _Code_, _Op0_) \
|
#define INST_1i(_Inst_, _Code_, _Op0_) \
|
||||||
ASMJIT_INLINE Error _Inst_(const _Op0_& o0) { return emit(_Code_, o0); } \
|
ASMJIT_INLINE Error _Inst_(const _Op0_& o0) { return emit(_Code_, o0); } \
|
||||||
/*! \overload */ \
|
/*! \overload */ \
|
||||||
@@ -607,12 +601,6 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
|
|||||||
return emit(_Code_, o0, o1); \
|
return emit(_Code_, o0, o1); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INST_2x_(_Inst_, _Code_, _Op0_, _Op1_, _Cond_) \
|
|
||||||
ASMJIT_INLINE Error _Inst_(const _Op0_& o0, const _Op1_& o1) { \
|
|
||||||
ASMJIT_ASSERT(_Cond_); \
|
|
||||||
return emit(_Code_, o0, o1); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define INST_2i(_Inst_, _Code_, _Op0_, _Op1_) \
|
#define INST_2i(_Inst_, _Code_, _Op0_, _Op1_) \
|
||||||
ASMJIT_INLINE Error _Inst_(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_, o0, o1); } \
|
ASMJIT_INLINE Error _Inst_(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_, o0, o1); } \
|
||||||
/*! \overload */ \
|
/*! \overload */ \
|
||||||
@@ -748,17 +736,17 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
|
|||||||
INST_2i(and_, kX86InstIdAnd, X86Mem, Imm)
|
INST_2i(and_, kX86InstIdAnd, X86Mem, Imm)
|
||||||
|
|
||||||
//! Bit scan forward.
|
//! Bit scan forward.
|
||||||
INST_2x_(bsf, kX86InstIdBsf, X86GpReg, X86GpReg, !o0.isGpb())
|
INST_2x(bsf, kX86InstIdBsf, X86GpReg, X86GpReg)
|
||||||
//! \overload
|
//! \overload
|
||||||
INST_2x_(bsf, kX86InstIdBsf, X86GpReg, X86Mem, !o0.isGpb())
|
INST_2x(bsf, kX86InstIdBsf, X86GpReg, X86Mem)
|
||||||
|
|
||||||
//! Bit scan reverse.
|
//! Bit scan reverse.
|
||||||
INST_2x_(bsr, kX86InstIdBsr, X86GpReg, X86GpReg, !o0.isGpb())
|
INST_2x(bsr, kX86InstIdBsr, X86GpReg, X86GpReg)
|
||||||
//! \overload
|
//! \overload
|
||||||
INST_2x_(bsr, kX86InstIdBsr, X86GpReg, X86Mem, !o0.isGpb())
|
INST_2x(bsr, kX86InstIdBsr, X86GpReg, X86Mem)
|
||||||
|
|
||||||
//! Byte swap (32-bit or 64-bit registers only) (i486).
|
//! Byte swap (32-bit or 64-bit registers only) (i486).
|
||||||
INST_1x_(bswap, kX86InstIdBswap, X86GpReg, o0.getSize() >= 4)
|
INST_1x(bswap, kX86InstIdBswap, X86GpReg)
|
||||||
|
|
||||||
//! Bit test.
|
//! Bit test.
|
||||||
INST_2x(bt, kX86InstIdBt, X86GpReg, X86GpReg)
|
INST_2x(bt, kX86InstIdBt, X86GpReg, X86GpReg)
|
||||||
@@ -919,7 +907,7 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
|
|||||||
INST_1cc(j, kX86InstIdJ, X86Util::condToJcc, Label)
|
INST_1cc(j, kX86InstIdJ, X86Util::condToJcc, Label)
|
||||||
|
|
||||||
//! Short jump if CX/ECX/RCX is zero.
|
//! Short jump if CX/ECX/RCX is zero.
|
||||||
INST_2x_(jecxz, kX86InstIdJecxz, X86GpReg, Label, o0.getRegIndex() == kX86RegIndexCx)
|
INST_2x(jecxz, kX86InstIdJecxz, X86GpReg, Label)
|
||||||
|
|
||||||
//! Jump.
|
//! Jump.
|
||||||
INST_1x(jmp, kX86InstIdJmp, X86GpReg)
|
INST_1x(jmp, kX86InstIdJmp, X86GpReg)
|
||||||
@@ -971,25 +959,23 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
|
|||||||
INST_2x(mov, kX86InstIdMov, X86SegReg, X86Mem)
|
INST_2x(mov, kX86InstIdMov, X86SegReg, X86Mem)
|
||||||
|
|
||||||
//! Move (AL|AX|EAX|RAX <- absolute address in immediate).
|
//! Move (AL|AX|EAX|RAX <- absolute address in immediate).
|
||||||
INST_2x_(mov_ptr, kX86InstIdMovPtr, X86GpReg, Imm, o0.getRegIndex() == 0);
|
INST_2x(mov_ptr, kX86InstIdMovPtr, X86GpReg, Imm);
|
||||||
//! \overload
|
//! \overload
|
||||||
ASMJIT_INLINE Error mov_ptr(const X86GpReg& o0, Ptr o1) {
|
ASMJIT_INLINE Error mov_ptr(const X86GpReg& o0, Ptr o1) {
|
||||||
ASMJIT_ASSERT(o0.getRegIndex() == 0);
|
|
||||||
return emit(kX86InstIdMovPtr, o0, Imm(o1));
|
return emit(kX86InstIdMovPtr, o0, Imm(o1));
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Move (absolute address in immediate <- AL|AX|EAX|RAX).
|
//! Move (absolute address in immediate <- AL|AX|EAX|RAX).
|
||||||
INST_2x_(mov_ptr, kX86InstIdMovPtr, Imm, X86GpReg, o1.getRegIndex() == 0);
|
INST_2x(mov_ptr, kX86InstIdMovPtr, Imm, X86GpReg);
|
||||||
//! \overload
|
//! \overload
|
||||||
ASMJIT_INLINE Error mov_ptr(Ptr o0, const X86GpReg& o1) {
|
ASMJIT_INLINE Error mov_ptr(Ptr o0, const X86GpReg& o1) {
|
||||||
ASMJIT_ASSERT(o1.getRegIndex() == 0);
|
|
||||||
return emit(kX86InstIdMovPtr, Imm(o0), o1);
|
return emit(kX86InstIdMovPtr, Imm(o0), o1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Move data after dwapping bytes (SSE3 - Atom).
|
//! Move data after dwapping bytes (SSE3 - Atom).
|
||||||
INST_2x_(movbe, kX86InstIdMovbe, X86GpReg, X86Mem, !o0.isGpb());
|
INST_2x(movbe, kX86InstIdMovbe, X86GpReg, X86Mem);
|
||||||
//! \overload
|
//! \overload
|
||||||
INST_2x_(movbe, kX86InstIdMovbe, X86Mem, X86GpReg, !o1.isGpb());
|
INST_2x(movbe, kX86InstIdMovbe, X86Mem, X86GpReg);
|
||||||
|
|
||||||
//! Move BYTE from DS:[ESI/RSI] to ES:[EDI/RDI].
|
//! Move BYTE from DS:[ESI/RSI] to ES:[EDI/RDI].
|
||||||
INST_0x(movsb, kX86InstIdMovsB)
|
INST_0x(movsb, kX86InstIdMovsB)
|
||||||
@@ -1045,14 +1031,14 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
|
|||||||
INST_2i(or_, kX86InstIdOr, X86Mem, Imm)
|
INST_2i(or_, kX86InstIdOr, X86Mem, Imm)
|
||||||
|
|
||||||
//! Pop a value from the stack.
|
//! Pop a value from the stack.
|
||||||
INST_1x_(pop, kX86InstIdPop, X86GpReg, o0.getSize() == 2 || o0.getSize() == _regSize)
|
INST_1x(pop, kX86InstIdPop, X86GpReg)
|
||||||
//! \overload
|
//! \overload
|
||||||
INST_1x_(pop, kX86InstIdPop, X86Mem, o0.getSize() == 2 || o0.getSize() == _regSize)
|
INST_1x(pop, kX86InstIdPop, X86Mem)
|
||||||
|
|
||||||
//! Pop a segment register from the stack.
|
//! Pop a segment register from the stack.
|
||||||
//!
|
//!
|
||||||
//! \note There is no instruction to pop a cs segment register.
|
//! \note There is no instruction to pop a cs segment register.
|
||||||
INST_1x_(pop, kX86InstIdPop, X86SegReg, o0.getRegIndex() != kX86SegCs);
|
INST_1x(pop, kX86InstIdPop, X86SegReg);
|
||||||
|
|
||||||
//! Pop all Gp registers - EDI|ESI|EBP|Ign|EBX|EDX|ECX|EAX (X86 Only).
|
//! Pop all Gp registers - EDI|ESI|EBP|Ign|EBX|EDX|ECX|EAX (X86 Only).
|
||||||
INST_0x(popa, kX86InstIdPopa)
|
INST_0x(popa, kX86InstIdPopa)
|
||||||
@@ -1061,9 +1047,9 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
|
|||||||
INST_0x(popf, kX86InstIdPopf)
|
INST_0x(popf, kX86InstIdPopf)
|
||||||
|
|
||||||
//! Push WORD or DWORD/QWORD on the stack.
|
//! Push WORD or DWORD/QWORD on the stack.
|
||||||
INST_1x_(push, kX86InstIdPush, X86GpReg, o0.getSize() == 2 || o0.getSize() == _regSize)
|
INST_1x(push, kX86InstIdPush, X86GpReg)
|
||||||
//! Push WORD or DWORD/QWORD on the stack.
|
//! Push WORD or DWORD/QWORD on the stack.
|
||||||
INST_1x_(push, kX86InstIdPush, X86Mem, o0.getSize() == 2 || o0.getSize() == _regSize)
|
INST_1x(push, kX86InstIdPush, X86Mem)
|
||||||
//! Push segment register on the stack.
|
//! Push segment register on the stack.
|
||||||
INST_1x(push, kX86InstIdPush, X86SegReg)
|
INST_1x(push, kX86InstIdPush, X86SegReg)
|
||||||
//! Push WORD or DWORD/QWORD on the stack.
|
//! Push WORD or DWORD/QWORD on the stack.
|
||||||
@@ -1356,7 +1342,7 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
|
|||||||
INST_0x(fabs, kX86InstIdFabs)
|
INST_0x(fabs, kX86InstIdFabs)
|
||||||
|
|
||||||
//! Add `o0 = o0 + o1` (one operand has to be `fp0`) (FPU).
|
//! Add `o0 = o0 + o1` (one operand has to be `fp0`) (FPU).
|
||||||
INST_2x_(fadd, kX86InstIdFadd, X86FpReg, X86FpReg, o0.getRegIndex() == 0 || o1.getRegIndex() == 0)
|
INST_2x(fadd, kX86InstIdFadd, X86FpReg, X86FpReg)
|
||||||
//! Add `fp0 = fp0 + float_or_double[o0]` (FPU).
|
//! Add `fp0 = fp0 + float_or_double[o0]` (FPU).
|
||||||
INST_1x(fadd, kX86InstIdFadd, X86Mem)
|
INST_1x(fadd, kX86InstIdFadd, X86Mem)
|
||||||
//! Add `o0 = o0 + fp0` and POP (FPU).
|
//! Add `o0 = o0 + fp0` and POP (FPU).
|
||||||
@@ -1418,7 +1404,7 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
|
|||||||
INST_0x(fdecstp, kX86InstIdFdecstp)
|
INST_0x(fdecstp, kX86InstIdFdecstp)
|
||||||
|
|
||||||
//! Divide `o0 = o0 / o1` (one has to be `fp0`) (FPU).
|
//! Divide `o0 = o0 / o1` (one has to be `fp0`) (FPU).
|
||||||
INST_2x_(fdiv, kX86InstIdFdiv, X86FpReg, X86FpReg, o0.getRegIndex() == 0 || o1.getRegIndex() == 0)
|
INST_2x(fdiv, kX86InstIdFdiv, X86FpReg, X86FpReg)
|
||||||
//! Divide `fp0 = fp0 / float_or_double[o0]` (FPU).
|
//! Divide `fp0 = fp0 / float_or_double[o0]` (FPU).
|
||||||
INST_1x(fdiv, kX86InstIdFdiv, X86Mem)
|
INST_1x(fdiv, kX86InstIdFdiv, X86Mem)
|
||||||
//! Divide `o0 = o0 / fp0` and POP (FPU).
|
//! Divide `o0 = o0 / fp0` and POP (FPU).
|
||||||
@@ -1427,7 +1413,7 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
|
|||||||
INST_0x(fdivp, kX86InstIdFdivp)
|
INST_0x(fdivp, kX86InstIdFdivp)
|
||||||
|
|
||||||
//! Reverse divide `o0 = o1 / o0` (one has to be `fp0`) (FPU).
|
//! Reverse divide `o0 = o1 / o0` (one has to be `fp0`) (FPU).
|
||||||
INST_2x_(fdivr, kX86InstIdFdivr, X86FpReg, X86FpReg, o0.getRegIndex() == 0 || o1.getRegIndex() == 0)
|
INST_2x(fdivr, kX86InstIdFdivr, X86FpReg, X86FpReg)
|
||||||
//! Reverse divide `fp0 = float_or_double[o0] / fp0` (FPU).
|
//! Reverse divide `fp0 = float_or_double[o0] / fp0` (FPU).
|
||||||
INST_1x(fdivr, kX86InstIdFdivr, X86Mem)
|
INST_1x(fdivr, kX86InstIdFdivr, X86Mem)
|
||||||
//! Reverse divide `o0 = fp0 / o0` and POP (FPU).
|
//! Reverse divide `o0 = fp0 / o0` and POP (FPU).
|
||||||
@@ -1439,20 +1425,20 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
|
|||||||
INST_1x(ffree, kX86InstIdFfree, X86FpReg)
|
INST_1x(ffree, kX86InstIdFfree, X86FpReg)
|
||||||
|
|
||||||
//! Add `fp0 = fp0 + short_or_int[o0]` (FPU).
|
//! Add `fp0 = fp0 + short_or_int[o0]` (FPU).
|
||||||
INST_1x_(fiadd, kX86InstIdFiadd, X86Mem, o0.getSize() == 2 || o0.getSize() == 4)
|
INST_1x(fiadd, kX86InstIdFiadd, X86Mem)
|
||||||
//! Compare `fp0` with `short_or_int[o0]` (FPU).
|
//! Compare `fp0` with `short_or_int[o0]` (FPU).
|
||||||
INST_1x_(ficom, kX86InstIdFicom, X86Mem, o0.getSize() == 2 || o0.getSize() == 4)
|
INST_1x(ficom, kX86InstIdFicom, X86Mem)
|
||||||
//! Compare `fp0` with `short_or_int[o0]` and POP (FPU).
|
//! Compare `fp0` with `short_or_int[o0]` and POP (FPU).
|
||||||
INST_1x_(ficomp, kX86InstIdFicomp, X86Mem, o0.getSize() == 2 || o0.getSize() == 4)
|
INST_1x(ficomp, kX86InstIdFicomp, X86Mem)
|
||||||
//! Divide `fp0 = fp0 / short_or_int[o0]` (FPU).
|
//! Divide `fp0 = fp0 / short_or_int[o0]` (FPU).
|
||||||
INST_1x_(fidiv, kX86InstIdFidiv, X86Mem, o0.getSize() == 2 || o0.getSize() == 4)
|
INST_1x(fidiv, kX86InstIdFidiv, X86Mem)
|
||||||
//! Reverse divide `fp0 = short_or_int[o0] / fp0` (FPU).
|
//! Reverse divide `fp0 = short_or_int[o0] / fp0` (FPU).
|
||||||
INST_1x_(fidivr, kX86InstIdFidivr, X86Mem, o0.getSize() == 2 || o0.getSize() == 4)
|
INST_1x(fidivr, kX86InstIdFidivr, X86Mem)
|
||||||
|
|
||||||
//! Load `short_or_int_or_long[o0]` and PUSH (FPU).
|
//! Load `short_or_int_or_long[o0]` and PUSH (FPU).
|
||||||
INST_1x_(fild, kX86InstIdFild, X86Mem, o0.getSize() == 2 || o0.getSize() == 4 || o0.getSize() == 8)
|
INST_1x(fild, kX86InstIdFild, X86Mem)
|
||||||
//! Multiply `fp0 *= short_or_int[o0]` (FPU).
|
//! Multiply `fp0 *= short_or_int[o0]` (FPU).
|
||||||
INST_1x_(fimul, kX86InstIdFimul, X86Mem, o0.getSize() == 2 || o0.getSize() == 4)
|
INST_1x(fimul, kX86InstIdFimul, X86Mem)
|
||||||
|
|
||||||
//! Increment FPU stack pointer (FPU).
|
//! Increment FPU stack pointer (FPU).
|
||||||
INST_0x(fincstp, kX86InstIdFincstp)
|
INST_0x(fincstp, kX86InstIdFincstp)
|
||||||
@@ -1460,20 +1446,20 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
|
|||||||
INST_0x(finit, kX86InstIdFinit)
|
INST_0x(finit, kX86InstIdFinit)
|
||||||
|
|
||||||
//! Subtract `fp0 = fp0 - short_or_int[o0]` (FPU).
|
//! Subtract `fp0 = fp0 - short_or_int[o0]` (FPU).
|
||||||
INST_1x_(fisub, kX86InstIdFisub, X86Mem, o0.getSize() == 2 || o0.getSize() == 4)
|
INST_1x(fisub, kX86InstIdFisub, X86Mem)
|
||||||
//! Reverse subtract `fp0 = short_or_int[o0] - fp0` (FPU).
|
//! Reverse subtract `fp0 = short_or_int[o0] - fp0` (FPU).
|
||||||
INST_1x_(fisubr, kX86InstIdFisubr, X86Mem, o0.getSize() == 2 || o0.getSize() == 4)
|
INST_1x(fisubr, kX86InstIdFisubr, X86Mem)
|
||||||
|
|
||||||
//! Initialize FPU without checking for pending unmasked exceptions (FPU).
|
//! Initialize FPU without checking for pending unmasked exceptions (FPU).
|
||||||
INST_0x(fninit, kX86InstIdFninit)
|
INST_0x(fninit, kX86InstIdFninit)
|
||||||
|
|
||||||
//! Store `fp0` as `short_or_int[o0]` (FPU).
|
//! Store `fp0` as `short_or_int[o0]` (FPU).
|
||||||
INST_1x_(fist, kX86InstIdFist, X86Mem, o0.getSize() == 2 || o0.getSize() == 4)
|
INST_1x(fist, kX86InstIdFist, X86Mem)
|
||||||
//! Store `fp0` as `short_or_int_or_long[o0]` and POP (FPU).
|
//! Store `fp0` as `short_or_int_or_long[o0]` and POP (FPU).
|
||||||
INST_1x_(fistp, kX86InstIdFistp, X86Mem, o0.getSize() == 2 || o0.getSize() == 4 || o0.getSize() == 8)
|
INST_1x(fistp, kX86InstIdFistp, X86Mem)
|
||||||
|
|
||||||
//! Load `float_or_double_or_extended[o0]` and PUSH (FPU).
|
//! Load `float_or_double_or_extended[o0]` and PUSH (FPU).
|
||||||
INST_1x_(fld, kX86InstIdFld, X86Mem, o0.getSize() == 4 || o0.getSize() == 8 || o0.getSize() == 10)
|
INST_1x(fld, kX86InstIdFld, X86Mem)
|
||||||
//! PUSH `o0` (FPU).
|
//! PUSH `o0` (FPU).
|
||||||
INST_1x(fld, kX86InstIdFld, X86FpReg)
|
INST_1x(fld, kX86InstIdFld, X86FpReg)
|
||||||
|
|
||||||
@@ -1498,7 +1484,7 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
|
|||||||
INST_1x(fldenv, kX86InstIdFldenv, X86Mem)
|
INST_1x(fldenv, kX86InstIdFldenv, X86Mem)
|
||||||
|
|
||||||
//! Multiply `o0 = o0 * o1` (one has to be `fp0`) (FPU).
|
//! Multiply `o0 = o0 * o1` (one has to be `fp0`) (FPU).
|
||||||
INST_2x_(fmul, kX86InstIdFmul, X86FpReg, X86FpReg, o0.getRegIndex() == 0 || o1.getRegIndex() == 0)
|
INST_2x(fmul, kX86InstIdFmul, X86FpReg, X86FpReg)
|
||||||
//! Multiply `fp0 = fp0 * float_or_double[o0]` (FPU).
|
//! Multiply `fp0 = fp0 * float_or_double[o0]` (FPU).
|
||||||
INST_1x(fmul, kX86InstIdFmul, X86Mem)
|
INST_1x(fmul, kX86InstIdFmul, X86Mem)
|
||||||
//! Multiply `o0 = o0 * fp0` and POP (FPU).
|
//! Multiply `o0 = o0 * fp0` and POP (FPU).
|
||||||
@@ -1518,7 +1504,7 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
|
|||||||
INST_1x(fnstcw, kX86InstIdFnstcw, X86Mem)
|
INST_1x(fnstcw, kX86InstIdFnstcw, X86Mem)
|
||||||
|
|
||||||
//! Store x87 FPU status word to `o0` (AX) (FPU).
|
//! Store x87 FPU status word to `o0` (AX) (FPU).
|
||||||
INST_1x_(fnstsw, kX86InstIdFnstsw, X86GpReg, o0.isRegCode(kX86RegTypeGpw, kX86RegIndexAx))
|
INST_1x(fnstsw, kX86InstIdFnstsw, X86GpReg)
|
||||||
//! Store x87 FPU status word to `word_ptr[o0]` (FPU).
|
//! Store x87 FPU status word to `word_ptr[o0]` (FPU).
|
||||||
INST_1x(fnstsw, kX86InstIdFnstsw, X86Mem)
|
INST_1x(fnstsw, kX86InstIdFnstsw, X86Mem)
|
||||||
|
|
||||||
@@ -1548,11 +1534,11 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
|
|||||||
INST_0x(fsqrt, kX86InstIdFsqrt)
|
INST_0x(fsqrt, kX86InstIdFsqrt)
|
||||||
|
|
||||||
//! Store floating point value to `float_or_double[o0]` (FPU).
|
//! Store floating point value to `float_or_double[o0]` (FPU).
|
||||||
INST_1x_(fst, kX86InstIdFst, X86Mem, o0.getSize() == 4 || o0.getSize() == 8)
|
INST_1x(fst, kX86InstIdFst, X86Mem)
|
||||||
//! Copy `o0 = fp0` (FPU).
|
//! Copy `o0 = fp0` (FPU).
|
||||||
INST_1x(fst, kX86InstIdFst, X86FpReg)
|
INST_1x(fst, kX86InstIdFst, X86FpReg)
|
||||||
//! Store floating point value to `float_or_double_or_extended[o0]` and POP (FPU).
|
//! Store floating point value to `float_or_double_or_extended[o0]` and POP (FPU).
|
||||||
INST_1x_(fstp, kX86InstIdFstp, X86Mem, o0.getSize() == 4 || o0.getSize() == 8 || o0.getSize() == 10)
|
INST_1x(fstp, kX86InstIdFstp, X86Mem)
|
||||||
//! Copy `o0 = fp0` and POP (FPU).
|
//! Copy `o0 = fp0` and POP (FPU).
|
||||||
INST_1x(fstp, kX86InstIdFstp, X86FpReg)
|
INST_1x(fstp, kX86InstIdFstp, X86FpReg)
|
||||||
|
|
||||||
@@ -1561,23 +1547,23 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
|
|||||||
//! Store x87 FPU environment to `[o0]` (14 or 28 bytes) (FPU).
|
//! Store x87 FPU environment to `[o0]` (14 or 28 bytes) (FPU).
|
||||||
INST_1x(fstenv, kX86InstIdFstenv, X86Mem)
|
INST_1x(fstenv, kX86InstIdFstenv, X86Mem)
|
||||||
//! Store x87 FPU status word to `o0` (AX) (FPU).
|
//! Store x87 FPU status word to `o0` (AX) (FPU).
|
||||||
INST_1x_(fstsw, kX86InstIdFstsw, X86GpReg, o0.getRegIndex() == kX86RegIndexAx)
|
INST_1x(fstsw, kX86InstIdFstsw, X86GpReg)
|
||||||
//! Store x87 FPU status word to `word_ptr[o0]` (FPU).
|
//! Store x87 FPU status word to `word_ptr[o0]` (FPU).
|
||||||
INST_1x(fstsw, kX86InstIdFstsw, X86Mem)
|
INST_1x(fstsw, kX86InstIdFstsw, X86Mem)
|
||||||
|
|
||||||
//! Subtract `o0 = o0 - o1` (one has to be `fp0`) (FPU).
|
//! Subtract `o0 = o0 - o1` (one has to be `fp0`) (FPU).
|
||||||
INST_2x_(fsub, kX86InstIdFsub, X86FpReg, X86FpReg, o0.getRegIndex() == 0 || o1.getRegIndex() == 0)
|
INST_2x(fsub, kX86InstIdFsub, X86FpReg, X86FpReg)
|
||||||
//! Subtract `fp0 = fp0 - float_or_double[o0]` (FPU).
|
//! Subtract `fp0 = fp0 - float_or_double[o0]` (FPU).
|
||||||
INST_1x_(fsub, kX86InstIdFsub, X86Mem, o0.getSize() == 4 || o0.getSize() == 8)
|
INST_1x(fsub, kX86InstIdFsub, X86Mem)
|
||||||
//! Subtract `o0 = o0 - fp0` and POP (FPU).
|
//! Subtract `o0 = o0 - fp0` and POP (FPU).
|
||||||
INST_1x(fsubp, kX86InstIdFsubp, X86FpReg)
|
INST_1x(fsubp, kX86InstIdFsubp, X86FpReg)
|
||||||
//! Subtract `fp1 = fp1 - fp0` and POP (FPU).
|
//! Subtract `fp1 = fp1 - fp0` and POP (FPU).
|
||||||
INST_0x(fsubp, kX86InstIdFsubp)
|
INST_0x(fsubp, kX86InstIdFsubp)
|
||||||
|
|
||||||
//! Reverse subtract `o0 = o1 - o0` (one has to be `fp0`) (FPU).
|
//! Reverse subtract `o0 = o1 - o0` (one has to be `fp0`) (FPU).
|
||||||
INST_2x_(fsubr, kX86InstIdFsubr, X86FpReg, X86FpReg, o0.getRegIndex() == 0 || o1.getRegIndex() == 0)
|
INST_2x(fsubr, kX86InstIdFsubr, X86FpReg, X86FpReg)
|
||||||
//! Reverse subtract `fp0 = fp0 - float_or_double[o0]` (FPU).
|
//! Reverse subtract `fp0 = fp0 - float_or_double[o0]` (FPU).
|
||||||
INST_1x_(fsubr, kX86InstIdFsubr, X86Mem, o0.getSize() == 4 || o0.getSize() == 8)
|
INST_1x(fsubr, kX86InstIdFsubr, X86Mem)
|
||||||
//! Reverse subtract `o0 = o0 - fp0` and POP (FPU).
|
//! Reverse subtract `o0 = o0 - fp0` and POP (FPU).
|
||||||
INST_1x(fsubrp, kX86InstIdFsubrp, X86FpReg)
|
INST_1x(fsubrp, kX86InstIdFsubrp, X86FpReg)
|
||||||
//! Reverse subtract `fp1 = fp1 - fp0` and POP (FPU).
|
//! Reverse subtract `fp1 = fp1 - fp0` and POP (FPU).
|
||||||
@@ -3434,9 +3420,9 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
|
|||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
//! Accumulate crc32 value (polynomial 0x11EDC6F41) (SSE4.2).
|
//! Accumulate crc32 value (polynomial 0x11EDC6F41) (SSE4.2).
|
||||||
INST_2x_(crc32, kX86InstIdCrc32, X86GpReg, X86GpReg, o0.isRegType(kX86RegTypeGpd) || o0.isRegType(kX86RegTypeGpq))
|
INST_2x(crc32, kX86InstIdCrc32, X86GpReg, X86GpReg)
|
||||||
//! \overload
|
//! \overload
|
||||||
INST_2x_(crc32, kX86InstIdCrc32, X86GpReg, X86Mem, o0.isRegType(kX86RegTypeGpd) || o0.isRegType(kX86RegTypeGpq))
|
INST_2x(crc32, kX86InstIdCrc32, X86GpReg, X86Mem)
|
||||||
|
|
||||||
//! Packed compare explicit length strings, return index (SSE4.2).
|
//! Packed compare explicit length strings, return index (SSE4.2).
|
||||||
INST_3i(pcmpestri, kX86InstIdPcmpestri, X86XmmReg, X86XmmReg, Imm)
|
INST_3i(pcmpestri, kX86InstIdPcmpestri, X86XmmReg, X86XmmReg, Imm)
|
||||||
@@ -3487,9 +3473,9 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
|
|||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
//! Return the count of number of bits set to 1 (POPCNT).
|
//! Return the count of number of bits set to 1 (POPCNT).
|
||||||
INST_2x_(popcnt, kX86InstIdPopcnt, X86GpReg, X86GpReg, !o0.isGpb() && o0.getRegType() == o1.getRegType())
|
INST_2x(popcnt, kX86InstIdPopcnt, X86GpReg, X86GpReg)
|
||||||
//! \overload
|
//! \overload
|
||||||
INST_2x_(popcnt, kX86InstIdPopcnt, X86GpReg, X86Mem, !o0.isGpb())
|
INST_2x(popcnt, kX86InstIdPopcnt, X86GpReg, X86Mem)
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// [LZCNT]
|
// [LZCNT]
|
||||||
@@ -6569,12 +6555,10 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
|
|||||||
#undef INST_0x
|
#undef INST_0x
|
||||||
|
|
||||||
#undef INST_1x
|
#undef INST_1x
|
||||||
#undef INST_1x_
|
|
||||||
#undef INST_1i
|
#undef INST_1i
|
||||||
#undef INST_1cc
|
#undef INST_1cc
|
||||||
|
|
||||||
#undef INST_2x
|
#undef INST_2x
|
||||||
#undef INST_2x_
|
|
||||||
#undef INST_2i
|
#undef INST_2i
|
||||||
#undef INST_2cc
|
#undef INST_2cc
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace asmjit {
|
|||||||
struct X86CallNode;
|
struct X86CallNode;
|
||||||
struct X86FuncNode;
|
struct X86FuncNode;
|
||||||
|
|
||||||
//! \addtogroup asmjit_x86_compiler
|
//! \addtogroup asmjit_x86
|
||||||
//! \{
|
//! \{
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -45,15 +45,15 @@ struct X86VarInfo {
|
|||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
//! Get register type, see `X86RegType`.
|
//! Get register type, see `X86RegType`.
|
||||||
ASMJIT_INLINE uint32_t getReg() const { return _reg; }
|
ASMJIT_INLINE uint32_t getReg() const noexcept { return _reg; }
|
||||||
//! Get register size in bytes.
|
//! Get register size in bytes.
|
||||||
ASMJIT_INLINE uint32_t getSize() const { return _size; }
|
ASMJIT_INLINE uint32_t getSize() const noexcept { return _size; }
|
||||||
//! Get variable class, see `RegClass`.
|
//! Get variable class, see `RegClass`.
|
||||||
ASMJIT_INLINE uint32_t getClass() const { return _class; }
|
ASMJIT_INLINE uint32_t getClass() const noexcept { return _class; }
|
||||||
//! Get variable description, see `VarFlag`.
|
//! Get variable description, see `VarFlag`.
|
||||||
ASMJIT_INLINE uint32_t getDesc() const { return _desc; }
|
ASMJIT_INLINE uint32_t getDesc() const noexcept { return _desc; }
|
||||||
//! Get variable type name.
|
//! Get variable type name.
|
||||||
ASMJIT_INLINE const char* getName() const { return _name; }
|
ASMJIT_INLINE const char* getName() const noexcept { return _name; }
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// [Members]
|
// [Members]
|
||||||
@@ -474,15 +474,18 @@ struct X86CallNode : public HLCall {
|
|||||||
//! - `kVarTypeUInt64` - Unsigned 64-bit integer, mapped to Gpq register (rax, rbx, ...).
|
//! - `kVarTypeUInt64` - Unsigned 64-bit integer, mapped to Gpq register (rax, rbx, ...).
|
||||||
//! - `kVarTypeIntPtr` - intptr_t, mapped to Gpd/Gpq register; depends on target, not host!
|
//! - `kVarTypeIntPtr` - intptr_t, mapped to Gpd/Gpq register; depends on target, not host!
|
||||||
//! - `kVarTypeUIntPtr` - uintptr_t, mapped to Gpd/Gpq register; depends on target, not host!
|
//! - `kVarTypeUIntPtr` - uintptr_t, mapped to Gpd/Gpq register; depends on target, not host!
|
||||||
//! - `kX86VarTypeMm` - 64-bit Mm register (mm0, mm1, ...).
|
//! - `kX86VarTypeMm` - 64-bit MMX register (mm0, mm1, ...).
|
||||||
//! - `kX86VarTypeXmm` - 128-bit SSE register.
|
//! - `kX86VarTypeXmm` - 128-bit XMM register.
|
||||||
//! - `kX86VarTypeXmmSs` - 128-bit SSE register that contains a scalar 32-bit SP-FP value.
|
//! - `kX86VarTypeXmmSs` - 128-bit XMM register that contains a scalar float.
|
||||||
//! - `kX86VarTypeXmmSd` - 128-bit SSE register that contains a scalar 64-bit DP-FP value.
|
//! - `kX86VarTypeXmmSd` - 128-bit XMM register that contains a scalar double.
|
||||||
//! - `kX86VarTypeXmmPs` - 128-bit SSE register that contains 4 packed 32-bit SP-FP values.
|
//! - `kX86VarTypeXmmPs` - 128-bit XMM register that contains 4 packed floats.
|
||||||
//! - `kX86VarTypeXmmPd` - 128-bit SSE register that contains 2 packed 64-bit DP-FP values.
|
//! - `kX86VarTypeXmmPd` - 128-bit XMM register that contains 2 packed doubles.
|
||||||
//! - `kX86VarTypeYmm` - 256-bit AVX register.
|
//! - `kX86VarTypeYmm` - 256-bit YMM register.
|
||||||
//! - `kX86VarTypeYmmPs` - 256-bit AVX register that contains 4 packed 32-bit SP-FP values.
|
//! - `kX86VarTypeYmmPs` - 256-bit YMM register that contains 8 packed floats.
|
||||||
//! - `kX86VarTypeYmmPd` - 256-bit AVX register that contains 2 packed 64-bit DP-FP values.
|
//! - `kX86VarTypeYmmPd` - 256-bit YMM register that contains 4 packed doubles.
|
||||||
|
//! - `kX86VarTypeZmm` - 512-bit ZMM register.
|
||||||
|
//! - `kX86VarTypeZmmPs` - 512-bit ZMM register that contains 16 packed floats.
|
||||||
|
//! - `kX86VarTypeZmmPd` - 512-bit ZMM register that contains 8 packed doubles.
|
||||||
//!
|
//!
|
||||||
//! List of X86/X64 variable states:
|
//! List of X86/X64 variable states:
|
||||||
//! - `kVarStateNone - State that is assigned to newly created variables or to
|
//! - `kVarStateNone - State that is assigned to newly created variables or to
|
||||||
|
|||||||
@@ -2399,8 +2399,8 @@ struct X86Util {
|
|||||||
//! Shuffle constants can be used to encode an immediate for these instructions:
|
//! Shuffle constants can be used to encode an immediate for these instructions:
|
||||||
//! - `X86Assembler::shufpd()` and `X86Compiler::shufpd()`
|
//! - `X86Assembler::shufpd()` and `X86Compiler::shufpd()`
|
||||||
static ASMJIT_INLINE int shuffle(uint32_t a, uint32_t b) {
|
static ASMJIT_INLINE int shuffle(uint32_t a, uint32_t b) {
|
||||||
|
ASMJIT_ASSERT(a <= 0x1 && b <= 0x1);
|
||||||
uint32_t result = (a << 1) | b;
|
uint32_t result = (a << 1) | b;
|
||||||
ASMJIT_ASSERT(result <= 0xFF);
|
|
||||||
return static_cast<int>(result);
|
return static_cast<int>(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2418,8 +2418,8 @@ struct X86Util {
|
|||||||
//! - `X86Assembler::pshuflw()` and `X86Compiler::pshuflw()`.
|
//! - `X86Assembler::pshuflw()` and `X86Compiler::pshuflw()`.
|
||||||
//! - `X86Assembler::shufps()` and `X86Compiler::shufps()`.
|
//! - `X86Assembler::shufps()` and `X86Compiler::shufps()`.
|
||||||
static ASMJIT_INLINE int shuffle(uint32_t a, uint32_t b, uint32_t c, uint32_t d) {
|
static ASMJIT_INLINE int shuffle(uint32_t a, uint32_t b, uint32_t c, uint32_t d) {
|
||||||
|
ASMJIT_ASSERT(a <= 0x3 && b <= 0x3 && c <= 0x3 && d <= 0x3);
|
||||||
uint32_t result = (a << 6) | (b << 4) | (c << 2) | d;
|
uint32_t result = (a << 6) | (b << 4) | (c << 2) | d;
|
||||||
ASMJIT_ASSERT(result <= 0xFF);
|
|
||||||
return static_cast<int>(result);
|
return static_cast<int>(result);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user