[ABI] Added ljmp, lcall, and lret instructions (fixes #310)

This commit is contained in:
kobalicek
2021-01-27 21:05:04 +01:00
parent 71fb24cb11
commit f36ea0c031
8 changed files with 2262 additions and 2183 deletions

View File

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

View File

@@ -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]
//! \}

View File

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

View File

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

View File

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

View File

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

View File

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