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:
parent
86ce502ae2
commit
b46c5545f1
1 changed files with 80 additions and 5 deletions
|
@ -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) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue