Added ASMJIT_NOEXCEPT macro

Replaced some inlined ASSERTs by runtime checks in X86Assembler.
This commit is contained in:
kobalicek
2016-01-05 18:46:18 +01:00
parent e5f7b8b533
commit bf8bba5bba
6 changed files with 157 additions and 136 deletions

View File

@@ -148,7 +148,7 @@ ASMJIT_ENUM(InstOptions) {
//! //!
//! - All instructions that clear the destination register if all operands //! - All instructions that clear the destination register if all operands
//! are the same, for example "xor x, x", "pcmpeqb", etc... //! are the same, for example "xor x, x", "pcmpeqb", etc...
//! //!
//! - Consecutive instructions that partially overwrite the variable until //! - Consecutive instructions that partially overwrite the variable until
//! there is no old content require the `overwrite()` to be used. Some //! there is no old content require the `overwrite()` to be used. Some
//! examples (not always the best use cases thought): //! examples (not always the best use cases thought):

View File

@@ -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.

View File

@@ -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());

View File

@@ -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

View File

@@ -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]
@@ -453,55 +453,58 @@ struct X86CallNode : public HLCall {
//! during the variable that its state is changed multiple times. To generate //! during the variable that its state is changed multiple times. To generate
//! a better code, you can control explicitely the allocation and spilling: //! a better code, you can control explicitely the allocation and spilling:
//! //!
//! - `alloc()` - Explicit method to alloc variable into register. It can be //! - `alloc()` - Explicit method to alloc variable into register. It can be
//! used to force allocation a variable before a loop for example. //! used to force allocation a variable before a loop for example.
//! //!
//! - `spill()` - Explicit method to spill variable. If variable is in //! - `spill()` - Explicit method to spill variable. If variable is in
//! register and you call this method, it's moved to its home memory //! register and you call this method, it's moved to its home memory
//! location. If the variable is not in register no operation is performed. //! location. If the variable is not in register no operation is performed.
//! //!
//! - `unuse()` - Unuse variable (you can use this to end the variable scope //! - `unuse()` - Unuse variable (you can use this to end the variable scope
//! or sub-scope). //! or sub-scope).
//! //!
//! List of X86/X64 variable types: //! List of X86/X64 variable types:
//! - `kVarTypeInt8` - Signed 8-bit integer, mapped to Gpd register (eax, ebx, ...). //! - `kVarTypeInt8` - Signed 8-bit integer, mapped to Gpd register (eax, ebx, ...).
//! - `kVarTypeUInt8` - Unsigned 8-bit integer, mapped to Gpd register (eax, ebx, ...). //! - `kVarTypeUInt8` - Unsigned 8-bit integer, mapped to Gpd register (eax, ebx, ...).
//! - `kVarTypeInt16` - Signed 16-bit integer, mapped to Gpd register (eax, ebx, ...). //! - `kVarTypeInt16` - Signed 16-bit integer, mapped to Gpd register (eax, ebx, ...).
//! - `kVarTypeUInt16` - Unsigned 16-bit integer, mapped to Gpd register (eax, ebx, ...). //! - `kVarTypeUInt16` - Unsigned 16-bit integer, mapped to Gpd register (eax, ebx, ...).
//! - `kVarTypeInt32` - Signed 32-bit integer, mapped to Gpd register (eax, ebx, ...). //! - `kVarTypeInt32` - Signed 32-bit integer, mapped to Gpd register (eax, ebx, ...).
//! - `kVarTypeUInt32` - Unsigned 32-bit integer, mapped to Gpd register (eax, ebx, ...). //! - `kVarTypeUInt32` - Unsigned 32-bit integer, mapped to Gpd register (eax, ebx, ...).
//! - `kVarTypeInt64` - Signed 64-bit integer, mapped to Gpq register (rax, rbx, ...). //! - `kVarTypeInt64` - Signed 64-bit integer, mapped to Gpq register (rax, rbx, ...).
//! - `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
//! not used variables (dereferenced to zero). //! not used variables (dereferenced to zero).
//! - `kVarStateReg - State that means that variable is currently allocated in //! - `kVarStateReg - State that means that variable is currently allocated in
//! register. //! register.
//! - `kVarStateMem - State that means that variable is currently only in //! - `kVarStateMem - State that means that variable is currently only in
//! memory location. //! memory location.
//! //!
//! Memory Management //! Memory Management
//! ----------------- //! -----------------
//! //!
//! Compiler Memory management follows these rules: //! Compiler Memory management follows these rules:
//! //!
//! - Everything created by `X86Compiler` is always freed by `X86Compiler`. //! - Everything created by `X86Compiler` is always freed by `X86Compiler`.
//! - To get a decent performance, compiler always uses large memory buffers //! - To get a decent performance, compiler always uses large memory buffers
//! to allocate objects. When the compiler is destroyed, it invalidates all //! to allocate objects. When the compiler is destroyed, it invalidates all
//! objects that it created. //! objects that it created.
//! - This type of memory management is called 'zone memory management'. //! - This type of memory management is called 'zone memory management'.
//! //!
//! In other words, anything that returns a pointer to something cannot be //! In other words, anything that returns a pointer to something cannot be
//! used after the compiler was destroyed. However, since compiler integrates //! used after the compiler was destroyed. However, since compiler integrates

View File

@@ -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);
} }
}; };