mirror of
https://github.com/asmjit/asmjit.git
synced 2025-12-17 12:34:35 +03:00
[ABI] Added ljmp, lcall, and lret instructions (fixes #310)
This commit is contained in:
@@ -432,40 +432,40 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
ASMJIT_INLINE void emitImmediate(uint64_t immValue, FastUInt8 immSize) noexcept {
|
ASMJIT_INLINE void emitImmediate(uint64_t immValue, FastUInt8 immSize) noexcept {
|
||||||
if (!immSize)
|
|
||||||
return;
|
|
||||||
|
|
||||||
#if ASMJIT_ARCH_BITS >= 64
|
#if ASMJIT_ARCH_BITS >= 64
|
||||||
uint64_t imm = uint64_t(immValue);
|
uint64_t imm = immValue;
|
||||||
|
if (immSize >= 4) {
|
||||||
|
emit32uLE(imm & 0xFFFFFFFFu);
|
||||||
|
imm >>= 32;
|
||||||
|
immSize -= 4;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
uint32_t imm = uint32_t(immValue & 0xFFFFFFFFu);
|
uint32_t imm = uint32_t(immValue & 0xFFFFFFFFu);
|
||||||
|
if (immSize >= 4) {
|
||||||
|
emit32uLE(imm);
|
||||||
|
imm = uint32_t(immValue >> 32);
|
||||||
|
immSize -= 4;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Many instructions just use a single byte immediate, so make it fast.
|
if (!immSize)
|
||||||
|
return;
|
||||||
emit8(imm & 0xFFu);
|
emit8(imm & 0xFFu);
|
||||||
if (--immSize == 0) return;
|
|
||||||
|
|
||||||
imm >>= 8;
|
imm >>= 8;
|
||||||
|
|
||||||
|
if (--immSize == 0)
|
||||||
|
return;
|
||||||
emit8(imm & 0xFFu);
|
emit8(imm & 0xFFu);
|
||||||
if (--immSize == 0) return;
|
|
||||||
|
|
||||||
imm >>= 8;
|
imm >>= 8;
|
||||||
|
|
||||||
|
if (--immSize == 0)
|
||||||
|
return;
|
||||||
emit8(imm & 0xFFu);
|
emit8(imm & 0xFFu);
|
||||||
if (--immSize == 0) return;
|
|
||||||
|
|
||||||
imm >>= 8;
|
imm >>= 8;
|
||||||
|
|
||||||
|
if (--immSize == 0)
|
||||||
|
return;
|
||||||
emit8(imm & 0xFFu);
|
emit8(imm & 0xFFu);
|
||||||
if (--immSize == 0) return;
|
|
||||||
|
|
||||||
// Can be 1, 2, 4 or 8 bytes, this handles the remaining high DWORD of an 8-byte immediate.
|
|
||||||
ASMJIT_ASSERT(immSize == 4);
|
|
||||||
|
|
||||||
#if ASMJIT_ARCH_BITS >= 64
|
|
||||||
imm >>= 8;
|
|
||||||
emit32uLE(uint32_t(imm));
|
|
||||||
#else
|
|
||||||
emit32uLE(uint32_t((uint64_t(immValue) >> 32) & 0xFFFFFFFFu));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1494,6 +1494,39 @@ CaseX86M_GPB_MulDiv:
|
|||||||
rmRel = &o0;
|
rmRel = &o0;
|
||||||
goto EmitJmpCall;
|
goto EmitJmpCall;
|
||||||
|
|
||||||
|
case InstDB::kEncodingX86LcallLjmp:
|
||||||
|
if (isign3 == ENC_OPS1(Mem)) {
|
||||||
|
rmRel = &o0;
|
||||||
|
uint32_t mSize = rmRel->size();
|
||||||
|
if (mSize == 0) {
|
||||||
|
mSize = registerSize();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mSize -= 2;
|
||||||
|
if (mSize != 2 && mSize != 4 && mSize != registerSize())
|
||||||
|
goto InvalidAddress;
|
||||||
|
}
|
||||||
|
opcode.addPrefixBySize(mSize);
|
||||||
|
goto EmitX86M;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isign3 == ENC_OPS2(Imm, Imm)) {
|
||||||
|
if (!is32Bit())
|
||||||
|
goto InvalidInstruction;
|
||||||
|
|
||||||
|
const Imm& imm0 = o0.as<Imm>();
|
||||||
|
const Imm& imm1 = o1.as<Imm>();
|
||||||
|
|
||||||
|
if (imm0.value() > 0xFFFFu || imm1.value() > 0xFFFFFFFFu)
|
||||||
|
goto InvalidImmediate;
|
||||||
|
|
||||||
|
opcode = x86AltOpcodeOf(instInfo);
|
||||||
|
immValue = imm1.value() | (imm0.value() << 32);
|
||||||
|
immSize = 6;
|
||||||
|
goto EmitX86Op;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case InstDB::kEncodingX86Lea:
|
case InstDB::kEncodingX86Lea:
|
||||||
if (isign3 == ENC_OPS2(Reg, Mem)) {
|
if (isign3 == ENC_OPS2(Reg, Mem)) {
|
||||||
opcode.addPrefixBySize(o0.size());
|
opcode.addPrefixBySize(o0.size());
|
||||||
|
|||||||
@@ -546,7 +546,11 @@ public:
|
|||||||
ASMJIT_INST_1x(jmp, Jmp, Mem) // ANY
|
ASMJIT_INST_1x(jmp, Jmp, Mem) // ANY
|
||||||
ASMJIT_INST_1x(jmp, Jmp, Label) // ANY
|
ASMJIT_INST_1x(jmp, Jmp, Label) // ANY
|
||||||
ASMJIT_INST_1x(jmp, Jmp, Imm) // ANY
|
ASMJIT_INST_1x(jmp, Jmp, Imm) // ANY
|
||||||
|
ASMJIT_INST_2x(lcall, Lcall, Imm, Imm) // ANY
|
||||||
|
ASMJIT_INST_1x(lcall, Lcall, Mem) // ANY
|
||||||
ASMJIT_INST_2x(lea, Lea, Gp, Mem) // ANY
|
ASMJIT_INST_2x(lea, Lea, Gp, Mem) // ANY
|
||||||
|
ASMJIT_INST_2x(ljmp, Ljmp, Imm, Imm) // ANY
|
||||||
|
ASMJIT_INST_1x(ljmp, Ljmp, Mem) // ANY
|
||||||
ASMJIT_INST_2x(lods, Lods, Gp_ZAX, DS_ZSI) // ANY [EXPLICIT]
|
ASMJIT_INST_2x(lods, Lods, Gp_ZAX, DS_ZSI) // ANY [EXPLICIT]
|
||||||
ASMJIT_INST_2x(loop, Loop, Gp_ZCX, Label) // ANY [EXPLICIT] Decrement xCX; short jump if xCX != 0.
|
ASMJIT_INST_2x(loop, Loop, Gp_ZCX, Label) // ANY [EXPLICIT] Decrement xCX; short jump if xCX != 0.
|
||||||
ASMJIT_INST_2x(loop, Loop, Gp_ZCX, Imm) // ANY [EXPLICIT] Decrement xCX; short jump if xCX != 0.
|
ASMJIT_INST_2x(loop, Loop, Gp_ZCX, Imm) // ANY [EXPLICIT] Decrement xCX; short jump if xCX != 0.
|
||||||
@@ -3777,6 +3781,8 @@ struct EmitterImplicitT : public EmitterExplicitT<This> {
|
|||||||
ASMJIT_INST_1x(mul, Mul, Mem) // ANY [IMPLICIT] {AX <- AL * m8} {xDX:xAX <- xAX * m16|m32|m64}
|
ASMJIT_INST_1x(mul, Mul, Mem) // ANY [IMPLICIT] {AX <- AL * m8} {xDX:xAX <- xAX * m16|m32|m64}
|
||||||
ASMJIT_INST_0x(ret, Ret)
|
ASMJIT_INST_0x(ret, Ret)
|
||||||
ASMJIT_INST_1x(ret, Ret, Imm)
|
ASMJIT_INST_1x(ret, Ret, Imm)
|
||||||
|
ASMJIT_INST_0x(lret, Lret)
|
||||||
|
ASMJIT_INST_1x(lret, Lret, Imm)
|
||||||
ASMJIT_INST_0x(xlatb, Xlatb) // ANY [IMPLICIT]
|
ASMJIT_INST_0x(xlatb, Xlatb) // ANY [IMPLICIT]
|
||||||
|
|
||||||
//! \}
|
//! \}
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ static const char* x86GetAddressSizeString(uint32_t size) noexcept {
|
|||||||
case 4 : return "dword ";
|
case 4 : return "dword ";
|
||||||
case 6 : return "fword ";
|
case 6 : return "fword ";
|
||||||
case 8 : return "qword ";
|
case 8 : return "qword ";
|
||||||
case 10: return "tword ";
|
case 10: return "tbyte ";
|
||||||
case 16: return "oword ";
|
case 16: return "oword ";
|
||||||
case 32: return "yword ";
|
case 32: return "yword ";
|
||||||
case 64: return "zword ";
|
case 64: return "zword ";
|
||||||
|
|||||||
@@ -424,6 +424,7 @@ struct Inst : public BaseInst {
|
|||||||
kIdKxorw, //!< Instruction 'kxorw' {AVX512_F}.
|
kIdKxorw, //!< Instruction 'kxorw' {AVX512_F}.
|
||||||
kIdLahf, //!< Instruction 'lahf' {LAHFSAHF}.
|
kIdLahf, //!< Instruction 'lahf' {LAHFSAHF}.
|
||||||
kIdLar, //!< Instruction 'lar'.
|
kIdLar, //!< Instruction 'lar'.
|
||||||
|
kIdLcall, //!< Instruction 'lcall'.
|
||||||
kIdLddqu, //!< Instruction 'lddqu' {SSE3}.
|
kIdLddqu, //!< Instruction 'lddqu' {SSE3}.
|
||||||
kIdLdmxcsr, //!< Instruction 'ldmxcsr' {SSE}.
|
kIdLdmxcsr, //!< Instruction 'ldmxcsr' {SSE}.
|
||||||
kIdLds, //!< Instruction 'lds' (X86).
|
kIdLds, //!< Instruction 'lds' (X86).
|
||||||
@@ -436,6 +437,7 @@ struct Inst : public BaseInst {
|
|||||||
kIdLgdt, //!< Instruction 'lgdt'.
|
kIdLgdt, //!< Instruction 'lgdt'.
|
||||||
kIdLgs, //!< Instruction 'lgs'.
|
kIdLgs, //!< Instruction 'lgs'.
|
||||||
kIdLidt, //!< Instruction 'lidt'.
|
kIdLidt, //!< Instruction 'lidt'.
|
||||||
|
kIdLjmp, //!< Instruction 'ljmp'.
|
||||||
kIdLldt, //!< Instruction 'lldt'.
|
kIdLldt, //!< Instruction 'lldt'.
|
||||||
kIdLlwpcb, //!< Instruction 'llwpcb' {LWP}.
|
kIdLlwpcb, //!< Instruction 'llwpcb' {LWP}.
|
||||||
kIdLmsw, //!< Instruction 'lmsw'.
|
kIdLmsw, //!< Instruction 'lmsw'.
|
||||||
@@ -443,6 +445,7 @@ struct Inst : public BaseInst {
|
|||||||
kIdLoop, //!< Instruction 'loop'.
|
kIdLoop, //!< Instruction 'loop'.
|
||||||
kIdLoope, //!< Instruction 'loope'.
|
kIdLoope, //!< Instruction 'loope'.
|
||||||
kIdLoopne, //!< Instruction 'loopne'.
|
kIdLoopne, //!< Instruction 'loopne'.
|
||||||
|
kIdLret, //!< Instruction 'lret'.
|
||||||
kIdLsl, //!< Instruction 'lsl'.
|
kIdLsl, //!< Instruction 'lsl'.
|
||||||
kIdLss, //!< Instruction 'lss'.
|
kIdLss, //!< Instruction 'lss'.
|
||||||
kIdLtr, //!< Instruction 'ltr'.
|
kIdLtr, //!< Instruction 'ltr'.
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -86,6 +86,7 @@ enum EncodingId : uint32_t {
|
|||||||
kEncodingX86JecxzLoop, //!< X86 jcxz, jecxz, jrcxz, loop, loope, loopne.
|
kEncodingX86JecxzLoop, //!< X86 jcxz, jecxz, jrcxz, loop, loope, loopne.
|
||||||
kEncodingX86Jmp, //!< X86 jmp.
|
kEncodingX86Jmp, //!< X86 jmp.
|
||||||
kEncodingX86JmpRel, //!< X86 xbegin.
|
kEncodingX86JmpRel, //!< X86 xbegin.
|
||||||
|
kEncodingX86LcallLjmp, //!< X86 lcall/ljmp.
|
||||||
kEncodingX86Lea, //!< X86 lea.
|
kEncodingX86Lea, //!< X86 lea.
|
||||||
kEncodingX86Mov, //!< X86 mov (all possible cases).
|
kEncodingX86Mov, //!< X86 mov (all possible cases).
|
||||||
kEncodingX86Movabs, //!< X86 movabs.
|
kEncodingX86Movabs, //!< X86 movabs.
|
||||||
|
|||||||
@@ -1099,7 +1099,9 @@ ASMJIT_MEM_PTR(ptr_512, 64)
|
|||||||
ASMJIT_MEM_PTR(byte_ptr, 1)
|
ASMJIT_MEM_PTR(byte_ptr, 1)
|
||||||
ASMJIT_MEM_PTR(word_ptr, 2)
|
ASMJIT_MEM_PTR(word_ptr, 2)
|
||||||
ASMJIT_MEM_PTR(dword_ptr, 4)
|
ASMJIT_MEM_PTR(dword_ptr, 4)
|
||||||
|
ASMJIT_MEM_PTR(fword_ptr, 6)
|
||||||
ASMJIT_MEM_PTR(qword_ptr, 8)
|
ASMJIT_MEM_PTR(qword_ptr, 8)
|
||||||
|
ASMJIT_MEM_PTR(tbyte_ptr, 10)
|
||||||
ASMJIT_MEM_PTR(tword_ptr, 10)
|
ASMJIT_MEM_PTR(tword_ptr, 10)
|
||||||
ASMJIT_MEM_PTR(oword_ptr, 16)
|
ASMJIT_MEM_PTR(oword_ptr, 16)
|
||||||
ASMJIT_MEM_PTR(dqword_ptr, 16)
|
ASMJIT_MEM_PTR(dqword_ptr, 16)
|
||||||
|
|||||||
@@ -165,6 +165,16 @@ bool testX86Assembler(const TestSettings& settings) noexcept {
|
|||||||
TEST_INSTRUCTION("8D043B" , lea(eax, ptr(ebx, edi)));
|
TEST_INSTRUCTION("8D043B" , lea(eax, ptr(ebx, edi)));
|
||||||
TEST_INSTRUCTION("8D0500000000" , lea(eax, ptr(0)));
|
TEST_INSTRUCTION("8D0500000000" , lea(eax, ptr(0)));
|
||||||
|
|
||||||
|
// LJMP/LCALL/LRET.
|
||||||
|
TEST_INSTRUCTION("66FF18" , lcall(dword_ptr(eax)));
|
||||||
|
TEST_INSTRUCTION("FF18" , lcall(fword_ptr(eax)));
|
||||||
|
TEST_INSTRUCTION("9A020000000100" , lcall(1, 2));
|
||||||
|
TEST_INSTRUCTION("66FF28" , ljmp(dword_ptr(eax)));
|
||||||
|
TEST_INSTRUCTION("FF28" , ljmp(fword_ptr(eax)));
|
||||||
|
TEST_INSTRUCTION("EA020000000100" , ljmp(1, 2));
|
||||||
|
TEST_INSTRUCTION("CB" , lret());
|
||||||
|
TEST_INSTRUCTION("CA0201" , lret(0x0102));
|
||||||
|
|
||||||
// XACQUIRE|XRELEASE|RTM.
|
// XACQUIRE|XRELEASE|RTM.
|
||||||
TEST_INSTRUCTION("C6F811" , xabort(0x11));
|
TEST_INSTRUCTION("C6F811" , xabort(0x11));
|
||||||
TEST_INSTRUCTION("F2F00108" , xacquire().lock().add(dword_ptr(eax), ecx));
|
TEST_INSTRUCTION("F2F00108" , xacquire().lock().add(dword_ptr(eax), ecx));
|
||||||
@@ -420,6 +430,16 @@ bool testX64Assembler(const TestSettings& settings) noexcept {
|
|||||||
TEST_INSTRUCTION("488D043B" , lea(rax, ptr(rbx, rdi)));
|
TEST_INSTRUCTION("488D043B" , lea(rax, ptr(rbx, rdi)));
|
||||||
TEST_INSTRUCTION("488D840000400000" , lea(rax, ptr(rax, rax, 0, 0x4000)));
|
TEST_INSTRUCTION("488D840000400000" , lea(rax, ptr(rax, rax, 0, 0x4000)));
|
||||||
|
|
||||||
|
// LJMP/LCALL/LRET.
|
||||||
|
TEST_INSTRUCTION("66FF18" , lcall(dword_ptr(rax)));
|
||||||
|
TEST_INSTRUCTION("FF18" , lcall(fword_ptr(rax)));
|
||||||
|
TEST_INSTRUCTION("48FF18" , lcall(tbyte_ptr(rax)));
|
||||||
|
TEST_INSTRUCTION("66FF28" , ljmp(dword_ptr(rax)));
|
||||||
|
TEST_INSTRUCTION("FF28" , ljmp(fword_ptr(rax)));
|
||||||
|
TEST_INSTRUCTION("48FF28" , ljmp(tbyte_ptr(rax)));
|
||||||
|
TEST_INSTRUCTION("CB" , lret());
|
||||||
|
TEST_INSTRUCTION("CA0201" , lret(0x0102));
|
||||||
|
|
||||||
// CRC32.
|
// CRC32.
|
||||||
TEST_INSTRUCTION("F20F38F0C7" , crc32(eax, bh));
|
TEST_INSTRUCTION("F20F38F0C7" , crc32(eax, bh));
|
||||||
TEST_INSTRUCTION("66F20F38F1C3" , crc32(eax, bx));
|
TEST_INSTRUCTION("66F20F38F1C3" , crc32(eax, bx));
|
||||||
|
|||||||
Reference in New Issue
Block a user