diff --git a/src/asmjit/base/assembler.h b/src/asmjit/base/assembler.h index a2ed9f4..e5a5560 100644 --- a/src/asmjit/base/assembler.h +++ b/src/asmjit/base/assembler.h @@ -148,7 +148,7 @@ ASMJIT_ENUM(InstOptions) { //! //! - All instructions that clear the destination register if all operands //! are the same, for example "xor x, x", "pcmpeqb", etc... - //! + //! //! - Consecutive instructions that partially overwrite the variable until //! there is no old content require the `overwrite()` to be used. Some //! examples (not always the best use cases thought): diff --git a/src/asmjit/build.h b/src/asmjit/build.h index 555353d..1553a7a 100644 --- a/src/asmjit/build.h +++ b/src/asmjit/build.h @@ -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. diff --git a/src/asmjit/x86/x86assembler.cpp b/src/asmjit/x86/x86assembler.cpp index 1279fc8..b1d1be3 100644 --- a/src/asmjit/x86/x86assembler.cpp +++ b/src/asmjit/x86/x86assembler.cpp @@ -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(o0)->getSize() == 2 || - static_cast(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(rmReg); goto _EmitFpuOp; } - else { + else if (rmReg == 0) { opCode = 0xDC00 + ((opCode >> 0) & 0xFF) + static_cast(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(o0)->getRegType() == kX86RegTypeGpd || - static_cast(o0)->getRegType() == kX86RegTypeGpq); + if (!Utils::inInterval(static_cast(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(o0)->getRegType() == kX86RegTypeGpd || - static_cast(o0)->getRegType() == kX86RegTypeGpq); + if (!Utils::inInterval(static_cast(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()); diff --git a/src/asmjit/x86/x86assembler.h b/src/asmjit/x86/x86assembler.h index ec235f2..21d45c5 100644 --- a/src/asmjit/x86/x86assembler.h +++ b/src/asmjit/x86/x86assembler.h @@ -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 diff --git a/src/asmjit/x86/x86compiler.h b/src/asmjit/x86/x86compiler.h index fb9ca12..bbed099 100644 --- a/src/asmjit/x86/x86compiler.h +++ b/src/asmjit/x86/x86compiler.h @@ -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] @@ -453,55 +453,58 @@ struct X86CallNode : public HLCall { //! during the variable that its state is changed multiple times. To generate //! a better code, you can control explicitely the allocation and spilling: //! -//! - `alloc()` - Explicit method to alloc variable into register. It can be -//! used to force allocation a variable before a loop for example. +//! - `alloc()` - Explicit method to alloc variable into register. It can be +//! used to force allocation a variable before a loop for example. //! -//! - `spill()` - Explicit method to spill variable. If variable is in -//! 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. +//! - `spill()` - Explicit method to spill variable. If variable is in +//! 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. //! -//! - `unuse()` - Unuse variable (you can use this to end the variable scope -//! or sub-scope). +//! - `unuse()` - Unuse variable (you can use this to end the variable scope +//! or sub-scope). //! //! List of X86/X64 variable types: -//! - `kVarTypeInt8` - Signed 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, ...). -//! - `kVarTypeUInt16` - Unsigned 16-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, ...). -//! - `kVarTypeInt64` - Signed 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! -//! - `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. +//! - `kVarTypeInt8` - Signed 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, ...). +//! - `kVarTypeUInt16` - Unsigned 16-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, ...). +//! - `kVarTypeInt64` - Signed 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! +//! - `kVarTypeUIntPtr` - uintptr_t, mapped to Gpd/Gpq register; depends on target, not host! +//! - `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 -//! not used variables (dereferenced to zero). -//! - `kVarStateReg - State that means that variable is currently allocated in -//! register. -//! - `kVarStateMem - State that means that variable is currently only in -//! memory location. +//! - `kVarStateNone - State that is assigned to newly created variables or to +//! not used variables (dereferenced to zero). +//! - `kVarStateReg - State that means that variable is currently allocated in +//! register. +//! - `kVarStateMem - State that means that variable is currently only in +//! memory location. //! //! Memory Management //! ----------------- //! //! Compiler Memory management follows these rules: //! -//! - Everything created by `X86Compiler` is always freed by `X86Compiler`. -//! - To get a decent performance, compiler always uses large memory buffers -//! to allocate objects. When the compiler is destroyed, it invalidates all -//! objects that it created. -//! - This type of memory management is called 'zone memory management'. +//! - Everything created by `X86Compiler` is always freed by `X86Compiler`. +//! - To get a decent performance, compiler always uses large memory buffers +//! to allocate objects. When the compiler is destroyed, it invalidates all +//! objects that it created. +//! - This type of memory management is called 'zone memory management'. //! //! In other words, anything that returns a pointer to something cannot be //! used after the compiler was destroyed. However, since compiler integrates diff --git a/src/asmjit/x86/x86inst.h b/src/asmjit/x86/x86inst.h index 86a5876..2c9ce72 100644 --- a/src/asmjit/x86/x86inst.h +++ b/src/asmjit/x86/x86inst.h @@ -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(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(result); } };