mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 03:17:34 +00:00
LibJIT: Add ModRM helpers for argument encoding
This commit is contained in:
parent
86ce502ae2
commit
b46c5545f1
1 changed files with 80 additions and 5 deletions
|
@ -117,6 +117,86 @@ struct Assembler {
|
||||||
return to_underlying(reg) & 0x7;
|
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)
|
void shift_right(Operand dst, Operand count)
|
||||||
{
|
{
|
||||||
VERIFY(dst.type == Operand::Type::Reg);
|
VERIFY(dst.type == Operand::Type::Reg);
|
||||||
|
@ -128,11 +208,6 @@ struct Assembler {
|
||||||
emit8(count.offset_or_immediate);
|
emit8(count.offset_or_immediate);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class Patchable {
|
|
||||||
Yes,
|
|
||||||
No,
|
|
||||||
};
|
|
||||||
|
|
||||||
void mov(Operand dst, Operand src, Patchable patchable = Patchable::No)
|
void mov(Operand dst, Operand src, Patchable patchable = Patchable::No)
|
||||||
{
|
{
|
||||||
if (dst.type == Operand::Type::Reg && src.type == Operand::Type::Reg) {
|
if (dst.type == Operand::Type::Reg && src.type == Operand::Type::Reg) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue