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

@@ -669,6 +669,16 @@
#endif
// [@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{@]
// \def ASMJIT_NOP
// 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());
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);
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)) {
ASMJIT_ASSERT(o0->getSize() != 1);
if (o0->getSize() == 1)
goto _IllegalInst;
opReg = x86OpReg(o0);
rmMem = x86OpMem(o1);
@@ -1208,6 +1210,9 @@ static ASMJIT_INLINE Error X86Assembler_emit(Assembler* self_, uint32_t code, co
case kX86InstEncodingIdX86BSwap:
if (encoded == ENC_OPS(Reg, None, None)) {
if (o0->getSize() < 4)
goto _IllegalInst;
opReg = x86OpReg(o0);
ADD_REX_W_BY_SIZE(o0->getSize());
goto _EmitX86OpWithOpReg;
@@ -1505,7 +1510,8 @@ static ASMJIT_INLINE Error X86Assembler_emit(Assembler* self_, uint32_t code, co
case kX86InstEncodingIdX86Jecxz:
if (encoded == ENC_OPS(Reg, Label, None)) {
ASMJIT_ASSERT(x86OpReg(o0) == kX86RegIndexCx);
if (x86OpReg(o0) != kX86RegIndexCx)
goto _IllegalInst;
if ((Arch == kArchX86 && o0->getSize() == 2) ||
(Arch == kArchX64 && o0->getSize() == 4)) {
@@ -1797,7 +1803,8 @@ static ASMJIT_INLINE Error X86Assembler_emit(Assembler* self_, uint32_t code, co
case kX86InstEncodingIdX86MovPtr:
if (encoded == ENC_OPS(Reg, Imm, None)) {
ASMJIT_ASSERT(x86OpReg(o0) == 0);
if (x86OpReg(o0) != 0)
goto _IllegalInst;
opCode += o0->getSize() != 1;
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();
if (encoded == ENC_OPS(Imm, Reg, None)) {
ASMJIT_ASSERT(x86OpReg(o1) == 0);
if (x86OpReg(o1) != 0)
goto _IllegalInst;
opCode += o1->getSize() != 1;
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 (o0->isRegType(kX86RegTypeSeg)) {
uint32_t segment = x86OpReg(o0);
ASMJIT_ASSERT(segment < kX86SegCount);
if (segment >= kX86SegCount)
goto _IllegalInst;
if (segment >= kX86SegFs)
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 (o0->isRegType(kX86RegTypeSeg)) {
uint32_t segment = x86OpReg(o0);
ASMJIT_ASSERT(segment < kX86SegCount);
if (segment == kX86SegCs || segment >= kX86SegCount)
goto _IllegalInst;
if (segment >= kX86SegFs)
EMIT_BYTE(0x0F);
@@ -1864,8 +1874,11 @@ static ASMJIT_INLINE Error X86Assembler_emit(Assembler* self_, uint32_t code, co
}
else {
_GroupPop_Gp:
ASMJIT_ASSERT(static_cast<const X86Reg*>(o0)->getSize() == 2 ||
static_cast<const X86Reg*>(o0)->getSize() == self->_regSize);
// We allow 2 byte, 4 byte, and 8 byte register sizes, althought PUSH
// 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();
opReg = x86OpReg(o0);
@@ -1876,8 +1889,10 @@ _GroupPop_Gp:
}
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);
goto _EmitX86M;
}
@@ -2142,10 +2157,13 @@ _EmitFpArith_Reg:
opCode = 0xD800 + ((opCode >> 8) & 0xFF) + static_cast<uint32_t>(rmReg);
goto _EmitFpuOp;
}
else {
else if (rmReg == 0) {
opCode = 0xDC00 + ((opCode >> 0) & 0xFF) + static_cast<uint32_t>(rmReg);
goto _EmitFpuOp;
}
else {
goto _IllegalInst;
}
}
if (encoded == ENC_OPS(Mem, None, None)) {
@@ -2272,8 +2290,8 @@ _EmitFpArith_Mem:
ADD_REX_W_BY_SIZE(o0->getSize());
if (encoded == ENC_OPS(Reg, Reg, None)) {
ASMJIT_ASSERT(static_cast<const Reg*>(o0)->getRegType() == kX86RegTypeGpd ||
static_cast<const Reg*>(o0)->getRegType() == kX86RegTypeGpq);
if (!Utils::inInterval<uint32_t>(static_cast<const X86Reg*>(o0)->getRegType(), kX86RegTypeGpd, kX86RegTypeGpq))
goto _IllegalInst;
opCode += o0->getSize() != 1;
opReg = x86OpReg(o0);
@@ -2282,8 +2300,8 @@ _EmitFpArith_Mem:
}
if (encoded == ENC_OPS(Reg, Mem, None)) {
ASMJIT_ASSERT(static_cast<const Reg*>(o0)->getRegType() == kX86RegTypeGpd ||
static_cast<const Reg*>(o0)->getRegType() == kX86RegTypeGpq);
if (!Utils::inInterval<uint32_t>(static_cast<const X86Reg*>(o0)->getRegType(), kX86RegTypeGpd, kX86RegTypeGpq))
goto _IllegalInst;
opCode += o0->getSize() != 1;
opReg = x86OpReg(o0);
@@ -2403,6 +2421,9 @@ _EmitFpArith_Mem:
case kX86InstEncodingIdExtMovBe:
if (encoded == ENC_OPS(Reg, Mem, None)) {
if (o0->getSize() == 1)
goto _IllegalInst;
ADD_66H_P_BY_SIZE(o0->getSize());
ADD_REX_W_BY_SIZE(o0->getSize());
@@ -2415,6 +2436,9 @@ _EmitFpArith_Mem:
opCode = extendedInfo.getSecondaryOpCode();
if (encoded == ENC_OPS(Mem, Reg, None)) {
if (o1->getSize() == 1)
goto _IllegalInst;
ADD_66H_P_BY_SIZE(o1->getSize());
ADD_REX_W_BY_SIZE(o1->getSize());

View File

@@ -18,7 +18,7 @@
namespace asmjit {
//! \addtogroup asmjit_x86_general
//! \addtogroup asmjit_x86
//! \{
// ============================================================================
@@ -28,91 +28,91 @@ namespace asmjit {
// \internal
#define ASMJIT_X86_EMIT_OPTIONS(T) \
/*! Force short form of jmp/jcc instruction. */ \
ASMJIT_INLINE T& short_() { \
ASMJIT_INLINE T& short_() noexcept { \
_instOptions |= kInstOptionShortForm; \
return *this; \
} \
\
/*! Force long form of jmp/jcc instruction. */ \
ASMJIT_INLINE T& long_() { \
ASMJIT_INLINE T& long_() noexcept { \
_instOptions |= kInstOptionLongForm; \
return *this; \
} \
\
/*! Condition is likely to be taken (has only benefit on P4). */ \
ASMJIT_INLINE T& taken() { \
ASMJIT_INLINE T& taken() noexcept { \
_instOptions |= kInstOptionTaken; \
return *this; \
} \
\
/*! Condition is unlikely to be taken (has only benefit on P4). */ \
ASMJIT_INLINE T& notTaken() { \
ASMJIT_INLINE T& notTaken() noexcept { \
_instOptions |= kInstOptionNotTaken; \
return *this; \
} \
\
/*! Use LOCK prefix. */ \
ASMJIT_INLINE T& lock() { \
ASMJIT_INLINE T& lock() noexcept { \
_instOptions |= kX86InstOptionLock; \
return *this; \
} \
\
/*! Force REX prefix (X64). */ \
ASMJIT_INLINE T& rex() { \
ASMJIT_INLINE T& rex() noexcept { \
_instOptions |= kX86InstOptionRex; \
return *this; \
} \
\
/*! Force 3-byte VEX prefix (AVX+). */ \
ASMJIT_INLINE T& vex3() { \
ASMJIT_INLINE T& vex3() noexcept { \
_instOptions |= kX86InstOptionVex3; \
return *this; \
} \
\
/*! Force 4-byte EVEX prefix (AVX512+). */ \
ASMJIT_INLINE T& evex() { \
ASMJIT_INLINE T& evex() noexcept { \
_instOptions |= kX86InstOptionEvex; \
return *this; \
} \
\
/*! Use zeroing instead of merging (AVX512+). */ \
ASMJIT_INLINE T& z() { \
ASMJIT_INLINE T& z() noexcept { \
_instOptions |= kX86InstOptionEvexZero; \
return *this; \
} \
\
/*! Broadcast one element to all other elements (AVX512+). */ \
ASMJIT_INLINE T& _1ToN() { \
ASMJIT_INLINE T& _1ToN() noexcept { \
_instOptions |= kX86InstOptionEvexOneN; \
return *this; \
} \
\
/*! Suppress all exceptions (AVX512+). */ \
ASMJIT_INLINE T& sae() { \
ASMJIT_INLINE T& sae() noexcept { \
_instOptions |= kX86InstOptionEvexSae; \
return *this; \
} \
\
/*! Static rounding mode `round-to-nearest` (even) and `SAE` (AVX512+). */ \
ASMJIT_INLINE T& rn_sae() { \
ASMJIT_INLINE T& rn_sae() noexcept { \
_instOptions |= kX86InstOptionEvexRnSae; \
return *this; \
} \
\
/*! Static rounding mode `round-down` (toward -inf) and `SAE` (AVX512+). */ \
ASMJIT_INLINE T& rd_sae() { \
ASMJIT_INLINE T& rd_sae() noexcept { \
_instOptions |= kX86InstOptionEvexRdSae; \
return *this; \
} \
\
/*! Static rounding mode `round-up` (toward +inf) and `SAE` (AVX512+). */ \
ASMJIT_INLINE T& ru_sae() { \
ASMJIT_INLINE T& ru_sae() noexcept { \
_instOptions |= kX86InstOptionEvexRuSae; \
return *this; \
} \
\
/*! Static rounding mode `round-toward-zero` (truncate) and `SAE` (AVX512+). */ \
ASMJIT_INLINE T& rz_sae() { \
ASMJIT_INLINE T& rz_sae() noexcept { \
_instOptions |= kX86InstOptionEvexRzSae; \
return *this; \
}
@@ -549,12 +549,6 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
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_) \
ASMJIT_INLINE Error _Inst_(const _Op0_& o0) { return emit(_Code_, o0); } \
/*! \overload */ \
@@ -607,12 +601,6 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
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_) \
ASMJIT_INLINE Error _Inst_(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_, o0, o1); } \
/*! \overload */ \
@@ -748,17 +736,17 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
INST_2i(and_, kX86InstIdAnd, X86Mem, Imm)
//! Bit scan forward.
INST_2x_(bsf, kX86InstIdBsf, X86GpReg, X86GpReg, !o0.isGpb())
INST_2x(bsf, kX86InstIdBsf, X86GpReg, X86GpReg)
//! \overload
INST_2x_(bsf, kX86InstIdBsf, X86GpReg, X86Mem, !o0.isGpb())
INST_2x(bsf, kX86InstIdBsf, X86GpReg, X86Mem)
//! Bit scan reverse.
INST_2x_(bsr, kX86InstIdBsr, X86GpReg, X86GpReg, !o0.isGpb())
INST_2x(bsr, kX86InstIdBsr, X86GpReg, X86GpReg)
//! \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).
INST_1x_(bswap, kX86InstIdBswap, X86GpReg, o0.getSize() >= 4)
INST_1x(bswap, kX86InstIdBswap, X86GpReg)
//! Bit test.
INST_2x(bt, kX86InstIdBt, X86GpReg, X86GpReg)
@@ -919,7 +907,7 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
INST_1cc(j, kX86InstIdJ, X86Util::condToJcc, Label)
//! Short jump if CX/ECX/RCX is zero.
INST_2x_(jecxz, kX86InstIdJecxz, X86GpReg, Label, o0.getRegIndex() == kX86RegIndexCx)
INST_2x(jecxz, kX86InstIdJecxz, X86GpReg, Label)
//! Jump.
INST_1x(jmp, kX86InstIdJmp, X86GpReg)
@@ -971,25 +959,23 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
INST_2x(mov, kX86InstIdMov, X86SegReg, X86Mem)
//! 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
ASMJIT_INLINE Error mov_ptr(const X86GpReg& o0, Ptr o1) {
ASMJIT_ASSERT(o0.getRegIndex() == 0);
return emit(kX86InstIdMovPtr, o0, Imm(o1));
}
//! 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
ASMJIT_INLINE Error mov_ptr(Ptr o0, const X86GpReg& o1) {
ASMJIT_ASSERT(o1.getRegIndex() == 0);
return emit(kX86InstIdMovPtr, Imm(o0), o1);
}
//! Move data after dwapping bytes (SSE3 - Atom).
INST_2x_(movbe, kX86InstIdMovbe, X86GpReg, X86Mem, !o0.isGpb());
INST_2x(movbe, kX86InstIdMovbe, X86GpReg, X86Mem);
//! \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].
INST_0x(movsb, kX86InstIdMovsB)
@@ -1045,14 +1031,14 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
INST_2i(or_, kX86InstIdOr, X86Mem, Imm)
//! Pop a value from the stack.
INST_1x_(pop, kX86InstIdPop, X86GpReg, o0.getSize() == 2 || o0.getSize() == _regSize)
INST_1x(pop, kX86InstIdPop, X86GpReg)
//! \overload
INST_1x_(pop, kX86InstIdPop, X86Mem, o0.getSize() == 2 || o0.getSize() == _regSize)
INST_1x(pop, kX86InstIdPop, X86Mem)
//! Pop a segment register from the stack.
//!
//! \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).
INST_0x(popa, kX86InstIdPopa)
@@ -1061,9 +1047,9 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
INST_0x(popf, kX86InstIdPopf)
//! 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.
INST_1x_(push, kX86InstIdPush, X86Mem, o0.getSize() == 2 || o0.getSize() == _regSize)
INST_1x(push, kX86InstIdPush, X86Mem)
//! Push segment register on the stack.
INST_1x(push, kX86InstIdPush, X86SegReg)
//! Push WORD or DWORD/QWORD on the stack.
@@ -1356,7 +1342,7 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
INST_0x(fabs, kX86InstIdFabs)
//! 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).
INST_1x(fadd, kX86InstIdFadd, X86Mem)
//! Add `o0 = o0 + fp0` and POP (FPU).
@@ -1418,7 +1404,7 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
INST_0x(fdecstp, kX86InstIdFdecstp)
//! 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).
INST_1x(fdiv, kX86InstIdFdiv, X86Mem)
//! Divide `o0 = o0 / fp0` and POP (FPU).
@@ -1427,7 +1413,7 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
INST_0x(fdivp, kX86InstIdFdivp)
//! 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).
INST_1x(fdivr, kX86InstIdFdivr, X86Mem)
//! Reverse divide `o0 = fp0 / o0` and POP (FPU).
@@ -1439,20 +1425,20 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
INST_1x(ffree, kX86InstIdFfree, X86FpReg)
//! 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).
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).
INST_1x_(ficomp, kX86InstIdFicomp, X86Mem, o0.getSize() == 2 || o0.getSize() == 4)
INST_1x(ficomp, kX86InstIdFicomp, X86Mem)
//! 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).
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).
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).
INST_1x_(fimul, kX86InstIdFimul, X86Mem, o0.getSize() == 2 || o0.getSize() == 4)
INST_1x(fimul, kX86InstIdFimul, X86Mem)
//! Increment FPU stack pointer (FPU).
INST_0x(fincstp, kX86InstIdFincstp)
@@ -1460,20 +1446,20 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
INST_0x(finit, kX86InstIdFinit)
//! 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).
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).
INST_0x(fninit, kX86InstIdFninit)
//! 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).
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).
INST_1x_(fld, kX86InstIdFld, X86Mem, o0.getSize() == 4 || o0.getSize() == 8 || o0.getSize() == 10)
INST_1x(fld, kX86InstIdFld, X86Mem)
//! PUSH `o0` (FPU).
INST_1x(fld, kX86InstIdFld, X86FpReg)
@@ -1498,7 +1484,7 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
INST_1x(fldenv, kX86InstIdFldenv, X86Mem)
//! 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).
INST_1x(fmul, kX86InstIdFmul, X86Mem)
//! Multiply `o0 = o0 * fp0` and POP (FPU).
@@ -1518,7 +1504,7 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
INST_1x(fnstcw, kX86InstIdFnstcw, X86Mem)
//! 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).
INST_1x(fnstsw, kX86InstIdFnstsw, X86Mem)
@@ -1548,11 +1534,11 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
INST_0x(fsqrt, kX86InstIdFsqrt)
//! 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).
INST_1x(fst, kX86InstIdFst, X86FpReg)
//! 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).
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).
INST_1x(fstenv, kX86InstIdFstenv, X86Mem)
//! 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).
INST_1x(fstsw, kX86InstIdFstsw, X86Mem)
//! 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).
INST_1x_(fsub, kX86InstIdFsub, X86Mem, o0.getSize() == 4 || o0.getSize() == 8)
INST_1x(fsub, kX86InstIdFsub, X86Mem)
//! Subtract `o0 = o0 - fp0` and POP (FPU).
INST_1x(fsubp, kX86InstIdFsubp, X86FpReg)
//! Subtract `fp1 = fp1 - fp0` and POP (FPU).
INST_0x(fsubp, kX86InstIdFsubp)
//! 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).
INST_1x_(fsubr, kX86InstIdFsubr, X86Mem, o0.getSize() == 4 || o0.getSize() == 8)
INST_1x(fsubr, kX86InstIdFsubr, X86Mem)
//! Reverse subtract `o0 = o0 - fp0` and POP (FPU).
INST_1x(fsubrp, kX86InstIdFsubrp, X86FpReg)
//! 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).
INST_2x_(crc32, kX86InstIdCrc32, X86GpReg, X86GpReg, o0.isRegType(kX86RegTypeGpd) || o0.isRegType(kX86RegTypeGpq))
INST_2x(crc32, kX86InstIdCrc32, X86GpReg, X86GpReg)
//! \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).
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).
INST_2x_(popcnt, kX86InstIdPopcnt, X86GpReg, X86GpReg, !o0.isGpb() && o0.getRegType() == o1.getRegType())
INST_2x(popcnt, kX86InstIdPopcnt, X86GpReg, X86GpReg)
//! \overload
INST_2x_(popcnt, kX86InstIdPopcnt, X86GpReg, X86Mem, !o0.isGpb())
INST_2x(popcnt, kX86InstIdPopcnt, X86GpReg, X86Mem)
// --------------------------------------------------------------------------
// [LZCNT]
@@ -6569,12 +6555,10 @@ struct ASMJIT_VIRTAPI X86Assembler : public Assembler {
#undef INST_0x
#undef INST_1x
#undef INST_1x_
#undef INST_1i
#undef INST_1cc
#undef INST_2x
#undef INST_2x_
#undef INST_2i
#undef INST_2cc

View File

@@ -29,7 +29,7 @@ namespace asmjit {
struct X86CallNode;
struct X86FuncNode;
//! \addtogroup asmjit_x86_compiler
//! \addtogroup asmjit_x86
//! \{
// ============================================================================
@@ -45,15 +45,15 @@ struct X86VarInfo {
// --------------------------------------------------------------------------
//! 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.
ASMJIT_INLINE uint32_t getSize() const { return _size; }
ASMJIT_INLINE uint32_t getSize() const noexcept { return _size; }
//! 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`.
ASMJIT_INLINE uint32_t getDesc() const { return _desc; }
ASMJIT_INLINE uint32_t getDesc() const noexcept { return _desc; }
//! Get variable type name.
ASMJIT_INLINE const char* getName() const { return _name; }
ASMJIT_INLINE const char* getName() const noexcept { return _name; }
// --------------------------------------------------------------------------
// [Members]
@@ -474,15 +474,18 @@ struct X86CallNode : public HLCall {
//! - `kVarTypeUInt64` - Unsigned 64-bit integer, mapped to Gpq register (rax, rbx, ...).
//! - `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!
//! - `kX86VarTypeMm` - 64-bit Mm register (mm0, mm1, ...).
//! - `kX86VarTypeXmm` - 128-bit SSE register.
//! - `kX86VarTypeXmmSs` - 128-bit SSE register that contains a scalar 32-bit SP-FP value.
//! - `kX86VarTypeXmmSd` - 128-bit SSE register that contains a scalar 64-bit DP-FP value.
//! - `kX86VarTypeXmmPs` - 128-bit SSE register that contains 4 packed 32-bit SP-FP values.
//! - `kX86VarTypeXmmPd` - 128-bit SSE register that contains 2 packed 64-bit DP-FP values.
//! - `kX86VarTypeYmm` - 256-bit AVX register.
//! - `kX86VarTypeYmmPs` - 256-bit AVX register that contains 4 packed 32-bit SP-FP values.
//! - `kX86VarTypeYmmPd` - 256-bit AVX register that contains 2 packed 64-bit DP-FP values.
//! - `kX86VarTypeMm` - 64-bit MMX register (mm0, mm1, ...).
//! - `kX86VarTypeXmm` - 128-bit XMM register.
//! - `kX86VarTypeXmmSs` - 128-bit XMM register that contains a scalar float.
//! - `kX86VarTypeXmmSd` - 128-bit XMM register that contains a scalar double.
//! - `kX86VarTypeXmmPs` - 128-bit XMM register that contains 4 packed floats.
//! - `kX86VarTypeXmmPd` - 128-bit XMM register that contains 2 packed doubles.
//! - `kX86VarTypeYmm` - 256-bit YMM register.
//! - `kX86VarTypeYmmPs` - 256-bit YMM register that contains 8 packed floats.
//! - `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:
//! - `kVarStateNone - State that is assigned to newly created variables or to

View File

@@ -2399,8 +2399,8 @@ struct X86Util {
//! Shuffle constants can be used to encode an immediate for these instructions:
//! - `X86Assembler::shufpd()` and `X86Compiler::shufpd()`
static ASMJIT_INLINE int shuffle(uint32_t a, uint32_t b) {
ASMJIT_ASSERT(a <= 0x1 && b <= 0x1);
uint32_t result = (a << 1) | b;
ASMJIT_ASSERT(result <= 0xFF);
return static_cast<int>(result);
}
@@ -2418,8 +2418,8 @@ struct X86Util {
//! - `X86Assembler::pshuflw()` and `X86Compiler::pshuflw()`.
//! - `X86Assembler::shufps()` and `X86Compiler::shufps()`.
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;
ASMJIT_ASSERT(result <= 0xFF);
return static_cast<int>(result);
}
};