1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 05:37:43 +00:00

LibJIT: Add ModRM helpers for argument encoding

This commit is contained in:
Hendiadyoin1 2023-10-28 17:11:16 +02:00 committed by Andreas Kling
parent 86ce502ae2
commit b46c5545f1

View file

@ -117,6 +117,86 @@ struct Assembler {
return to_underlying(reg) & 0x7;
}
enum class Patchable {
Yes,
No,
};
union ModRM {
static constexpr u8 Mem = 0b00;
static constexpr u8 MemDisp8 = 0b01;
static constexpr u8 MemDisp32 = 0b10;
static constexpr u8 Reg = 0b11;
struct {
u8 rm : 3;
u8 reg : 3;
u8 mode : 2;
};
u8 raw;
};
void emit_modrm_slash(u8 slash, Operand rm, Patchable patchable = Patchable::No)
{
ModRM raw;
raw.rm = encode_reg(rm.reg);
raw.reg = slash;
emit_modrm(raw, rm, patchable);
}
void emit_modrm_rm(Operand dst, Operand src, Patchable patchable = Patchable::No)
{
VERIFY(dst.type == Operand::Type::Reg);
ModRM raw {};
raw.reg = encode_reg(dst.reg);
raw.rm = encode_reg(src.reg);
emit_modrm(raw, src, patchable);
}
void emit_modrm_mr(Operand dst, Operand src, Patchable patchable = Patchable::No)
{
VERIFY(src.type == Operand::Type::Reg);
ModRM raw {};
raw.reg = encode_reg(src.reg);
raw.rm = encode_reg(dst.reg);
emit_modrm(raw, dst, patchable);
}
void emit_modrm(ModRM raw, Operand rm, Patchable patchable)
{
// FIXME: rm:100 (RSP) is reserved as the SIB marker
VERIFY(rm.type != Operand::Type::Imm);
switch (rm.type) {
case Operand::Type::Reg:
// FIXME: There is mod:00,rm:101(EBP?) -> disp32, that might be something else
raw.mode = ModRM::Reg;
emit8(raw.raw);
break;
case Operand::Type::Mem64BaseAndOffset: {
auto disp = rm.offset_or_immediate;
if (patchable == Patchable::Yes) {
raw.mode = ModRM::MemDisp32;
emit8(raw.raw);
emit32(disp);
} else if (disp == 0) {
raw.mode = ModRM::Mem;
emit8(raw.raw);
} else if (static_cast<i64>(disp) >= -128 && disp <= 127) {
raw.mode = ModRM::MemDisp8;
emit8(raw.raw);
emit8(disp & 0xff);
} else {
raw.mode = ModRM::MemDisp32;
emit8(raw.raw);
emit32(disp);
}
break;
}
case Operand::Type::Imm:
VERIFY_NOT_REACHED();
}
}
void shift_right(Operand dst, Operand count)
{
VERIFY(dst.type == Operand::Type::Reg);
@ -128,11 +208,6 @@ struct Assembler {
emit8(count.offset_or_immediate);
}
enum class Patchable {
Yes,
No,
};
void mov(Operand dst, Operand src, Patchable patchable = Patchable::No)
{
if (dst.type == Operand::Type::Reg && src.type == Operand::Type::Reg) {