1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 05:47:35 +00:00

LibJIT: Emit all Jcc jump instructions from one function

Since all conditional instructions use a certain number of bits to
encode the condition type (from my observation of `Jcc`, `SETcc` and
`CMOVcc`), let's abuse that to deduplicate some code!

This adds a `Condition` enum that defines the type of condition we are
jumping based on, whose underlying values are the values that must be
encoded to trigger each condition.
This commit is contained in:
Zaggy1024 2023-10-29 04:54:52 -05:00 committed by Andreas Kling
parent e717961000
commit 288aff01cd

View file

@ -99,6 +99,19 @@ struct Assembler {
} }
}; };
enum class Condition {
EqualTo = 0x4,
NotEqualTo = 0x5,
UnsignedGreaterThan = 0x7,
UnsignedGreaterThanOrEqualTo = 0x3,
UnsignedLessThan = 0x2,
UnsignedLessThanOrEqualTo = 0x6,
SignedGreaterThan = 0xF,
SignedGreaterThanOrEqualTo = 0xD,
SignedLessThan = 0xC,
SignedLessThanOrEqualTo = 0xE,
};
static constexpr u8 encode_reg(Reg reg) static constexpr u8 encode_reg(Reg reg)
{ {
return to_underlying(reg) & 0x7; return to_underlying(reg) & 0x7;
@ -335,69 +348,39 @@ struct Assembler {
} }
} }
void jump_if_zero(Operand reg, Label& label) void jump_if(Operand lhs, Condition condition, Operand rhs, Label& label)
{ {
test(reg, reg); cmp(lhs, rhs);
// jz label (RIP-relative 32-bit offset) emit8(0x0F);
emit8(0x0f); emit8(0x80 | to_underlying(condition));
emit8(0x84);
emit32(0xdeadbeef); emit32(0xdeadbeef);
label.add_jump(*this, m_output.size()); label.add_jump(*this, m_output.size());
} }
void jump_if_zero(Operand reg, Label& label)
{
jump_if(reg, Condition::EqualTo, Operand::Imm(0), label);
}
void jump_if_not_zero(Operand reg, Label& label) void jump_if_not_zero(Operand reg, Label& label)
{ {
test(reg, reg); jump_if(reg, Condition::NotEqualTo, Operand::Imm(0), label);
// jnz label (RIP-relative 32-bit offset)
emit8(0x0f);
emit8(0x85);
emit32(0xdeadbeef);
label.add_jump(*this, m_output.size());
} }
void jump_if_equal(Operand lhs, Operand rhs, Label& label) void jump_if_equal(Operand lhs, Operand rhs, Label& label)
{ {
if (rhs.type == Operand::Type::Imm && rhs.offset_or_immediate == 0) { jump_if(lhs, Condition::EqualTo, rhs, label);
jump_if_zero(lhs, label);
return;
}
cmp(lhs, rhs);
// je label (RIP-relative 32-bit offset)
emit8(0x0f);
emit8(0x84);
emit32(0xdeadbeef);
label.add_jump(*this, m_output.size());
} }
void jump_if_not_equal(Operand lhs, Operand rhs, Label& label) void jump_if_not_equal(Operand lhs, Operand rhs, Label& label)
{ {
if (rhs.type == Operand::Type::Imm && rhs.offset_or_immediate == 0) { jump_if(lhs, Condition::NotEqualTo, rhs, label);
jump_if_not_zero(lhs, label);
return;
}
cmp(lhs, rhs);
// jne label (RIP-relative 32-bit offset)
emit8(0x0f);
emit8(0x85);
emit32(0xdeadbeef);
label.add_jump(*this, m_output.size());
} }
void jump_if_less_than(Operand lhs, Operand rhs, Label& label) void jump_if_less_than(Operand lhs, Operand rhs, Label& label)
{ {
cmp(lhs, rhs); jump_if(lhs, Condition::SignedLessThan, rhs, label);
// jl label (RIP-relative 32-bit offset)
emit8(0x0f);
emit8(0x8c);
emit32(0xdeadbeef);
label.add_jump(*this, m_output.size());
} }
void jump_if_overflow(Label& label) void jump_if_overflow(Label& label)