mirror of
https://github.com/asmjit/asmjit.git
synced 2025-12-16 20:17:05 +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 {
|
||||
if (!immSize)
|
||||
return;
|
||||
|
||||
#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
|
||||
uint32_t imm = uint32_t(immValue & 0xFFFFFFFFu);
|
||||
if (immSize >= 4) {
|
||||
emit32uLE(imm);
|
||||
imm = uint32_t(immValue >> 32);
|
||||
immSize -= 4;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Many instructions just use a single byte immediate, so make it fast.
|
||||
if (!immSize)
|
||||
return;
|
||||
emit8(imm & 0xFFu);
|
||||
if (--immSize == 0) return;
|
||||
|
||||
imm >>= 8;
|
||||
|
||||
if (--immSize == 0)
|
||||
return;
|
||||
emit8(imm & 0xFFu);
|
||||
if (--immSize == 0) return;
|
||||
|
||||
imm >>= 8;
|
||||
|
||||
if (--immSize == 0)
|
||||
return;
|
||||
emit8(imm & 0xFFu);
|
||||
if (--immSize == 0) return;
|
||||
|
||||
imm >>= 8;
|
||||
|
||||
if (--immSize == 0)
|
||||
return;
|
||||
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;
|
||||
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:
|
||||
if (isign3 == ENC_OPS2(Reg, Mem)) {
|
||||
opcode.addPrefixBySize(o0.size());
|
||||
|
||||
@@ -546,7 +546,11 @@ public:
|
||||
ASMJIT_INST_1x(jmp, Jmp, Mem) // ANY
|
||||
ASMJIT_INST_1x(jmp, Jmp, Label) // 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(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(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.
|
||||
@@ -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_0x(ret, Ret)
|
||||
ASMJIT_INST_1x(ret, Ret, Imm)
|
||||
ASMJIT_INST_0x(lret, Lret)
|
||||
ASMJIT_INST_1x(lret, Lret, Imm)
|
||||
ASMJIT_INST_0x(xlatb, Xlatb) // ANY [IMPLICIT]
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -193,7 +193,7 @@ static const char* x86GetAddressSizeString(uint32_t size) noexcept {
|
||||
case 4 : return "dword ";
|
||||
case 6 : return "fword ";
|
||||
case 8 : return "qword ";
|
||||
case 10: return "tword ";
|
||||
case 10: return "tbyte ";
|
||||
case 16: return "oword ";
|
||||
case 32: return "yword ";
|
||||
case 64: return "zword ";
|
||||
|
||||
@@ -424,6 +424,7 @@ struct Inst : public BaseInst {
|
||||
kIdKxorw, //!< Instruction 'kxorw' {AVX512_F}.
|
||||
kIdLahf, //!< Instruction 'lahf' {LAHFSAHF}.
|
||||
kIdLar, //!< Instruction 'lar'.
|
||||
kIdLcall, //!< Instruction 'lcall'.
|
||||
kIdLddqu, //!< Instruction 'lddqu' {SSE3}.
|
||||
kIdLdmxcsr, //!< Instruction 'ldmxcsr' {SSE}.
|
||||
kIdLds, //!< Instruction 'lds' (X86).
|
||||
@@ -436,6 +437,7 @@ struct Inst : public BaseInst {
|
||||
kIdLgdt, //!< Instruction 'lgdt'.
|
||||
kIdLgs, //!< Instruction 'lgs'.
|
||||
kIdLidt, //!< Instruction 'lidt'.
|
||||
kIdLjmp, //!< Instruction 'ljmp'.
|
||||
kIdLldt, //!< Instruction 'lldt'.
|
||||
kIdLlwpcb, //!< Instruction 'llwpcb' {LWP}.
|
||||
kIdLmsw, //!< Instruction 'lmsw'.
|
||||
@@ -443,6 +445,7 @@ struct Inst : public BaseInst {
|
||||
kIdLoop, //!< Instruction 'loop'.
|
||||
kIdLoope, //!< Instruction 'loope'.
|
||||
kIdLoopne, //!< Instruction 'loopne'.
|
||||
kIdLret, //!< Instruction 'lret'.
|
||||
kIdLsl, //!< Instruction 'lsl'.
|
||||
kIdLss, //!< Instruction 'lss'.
|
||||
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.
|
||||
kEncodingX86Jmp, //!< X86 jmp.
|
||||
kEncodingX86JmpRel, //!< X86 xbegin.
|
||||
kEncodingX86LcallLjmp, //!< X86 lcall/ljmp.
|
||||
kEncodingX86Lea, //!< X86 lea.
|
||||
kEncodingX86Mov, //!< X86 mov (all possible cases).
|
||||
kEncodingX86Movabs, //!< X86 movabs.
|
||||
|
||||
@@ -1099,7 +1099,9 @@ ASMJIT_MEM_PTR(ptr_512, 64)
|
||||
ASMJIT_MEM_PTR(byte_ptr, 1)
|
||||
ASMJIT_MEM_PTR(word_ptr, 2)
|
||||
ASMJIT_MEM_PTR(dword_ptr, 4)
|
||||
ASMJIT_MEM_PTR(fword_ptr, 6)
|
||||
ASMJIT_MEM_PTR(qword_ptr, 8)
|
||||
ASMJIT_MEM_PTR(tbyte_ptr, 10)
|
||||
ASMJIT_MEM_PTR(tword_ptr, 10)
|
||||
ASMJIT_MEM_PTR(oword_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("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.
|
||||
TEST_INSTRUCTION("C6F811" , xabort(0x11));
|
||||
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("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.
|
||||
TEST_INSTRUCTION("F20F38F0C7" , crc32(eax, bh));
|
||||
TEST_INSTRUCTION("66F20F38F1C3" , crc32(eax, bx));
|
||||
|
||||
Reference in New Issue
Block a user