mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-24 10:22:05 -05:00
LibJIT: Add floating-point registers
Co-authored-by: Stephan Vedder <vedder@mbits.info>
This commit is contained in:
parent
5557f05bb5
commit
a698c51a5b
1 changed files with 50 additions and 6 deletions
|
@ -36,11 +36,28 @@ struct X86_64Assembler {
|
||||||
R13 = 13,
|
R13 = 13,
|
||||||
R14 = 14,
|
R14 = 14,
|
||||||
R15 = 15,
|
R15 = 15,
|
||||||
|
XMM0 = 0,
|
||||||
|
XMM1 = 1,
|
||||||
|
XMM2 = 2,
|
||||||
|
XMM3 = 3,
|
||||||
|
XMM4 = 4,
|
||||||
|
XMM5 = 5,
|
||||||
|
XMM6 = 6,
|
||||||
|
XMM7 = 7,
|
||||||
|
XMM8 = 8,
|
||||||
|
XMM9 = 9,
|
||||||
|
XMM10 = 10,
|
||||||
|
XMM11 = 11,
|
||||||
|
XMM12 = 12,
|
||||||
|
XMM13 = 13,
|
||||||
|
XMM14 = 14,
|
||||||
|
XMM15 = 15,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Operand {
|
struct Operand {
|
||||||
enum class Type {
|
enum class Type {
|
||||||
Reg,
|
Reg,
|
||||||
|
FReg,
|
||||||
Imm,
|
Imm,
|
||||||
Mem64BaseAndOffset,
|
Mem64BaseAndOffset,
|
||||||
};
|
};
|
||||||
|
@ -58,6 +75,14 @@ struct X86_64Assembler {
|
||||||
return operand;
|
return operand;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Operand FloatRegister(Reg reg)
|
||||||
|
{
|
||||||
|
Operand operand;
|
||||||
|
operand.type = Type::FReg;
|
||||||
|
operand.reg = reg;
|
||||||
|
return operand;
|
||||||
|
}
|
||||||
|
|
||||||
static Operand Imm(u64 imm)
|
static Operand Imm(u64 imm)
|
||||||
{
|
{
|
||||||
Operand operand;
|
Operand operand;
|
||||||
|
@ -149,7 +174,7 @@ struct X86_64Assembler {
|
||||||
|
|
||||||
void emit_modrm_rm(Operand dst, Operand src, Patchable patchable = Patchable::No)
|
void emit_modrm_rm(Operand dst, Operand src, Patchable patchable = Patchable::No)
|
||||||
{
|
{
|
||||||
VERIFY(dst.type == Operand::Type::Reg);
|
VERIFY(dst.type == Operand::Type::Reg || dst.type == Operand::Type::FReg);
|
||||||
ModRM raw {};
|
ModRM raw {};
|
||||||
raw.reg = encode_reg(dst.reg);
|
raw.reg = encode_reg(dst.reg);
|
||||||
raw.rm = encode_reg(src.reg);
|
raw.rm = encode_reg(src.reg);
|
||||||
|
@ -158,7 +183,7 @@ struct X86_64Assembler {
|
||||||
|
|
||||||
void emit_modrm_mr(Operand dst, Operand src, Patchable patchable = Patchable::No)
|
void emit_modrm_mr(Operand dst, Operand src, Patchable patchable = Patchable::No)
|
||||||
{
|
{
|
||||||
VERIFY(src.type == Operand::Type::Reg);
|
VERIFY(src.type == Operand::Type::Reg || src.type == Operand::Type::FReg);
|
||||||
ModRM raw {};
|
ModRM raw {};
|
||||||
raw.reg = encode_reg(src.reg);
|
raw.reg = encode_reg(src.reg);
|
||||||
raw.rm = encode_reg(dst.reg);
|
raw.rm = encode_reg(dst.reg);
|
||||||
|
@ -171,6 +196,7 @@ struct X86_64Assembler {
|
||||||
VERIFY(rm.type != Operand::Type::Imm);
|
VERIFY(rm.type != Operand::Type::Imm);
|
||||||
|
|
||||||
switch (rm.type) {
|
switch (rm.type) {
|
||||||
|
case Operand::Type::FReg:
|
||||||
case Operand::Type::Reg:
|
case Operand::Type::Reg:
|
||||||
// FIXME: There is mod:00,rm:101(EBP?) -> disp32, that might be something else
|
// FIXME: There is mod:00,rm:101(EBP?) -> disp32, that might be something else
|
||||||
raw.mode = ModRM::Reg;
|
raw.mode = ModRM::Reg;
|
||||||
|
@ -239,8 +265,8 @@ struct X86_64Assembler {
|
||||||
}
|
}
|
||||||
void emit_rex_for_mr(Operand dst, Operand src, REX_W W)
|
void emit_rex_for_mr(Operand dst, Operand src, REX_W W)
|
||||||
{
|
{
|
||||||
VERIFY(dst.is_register_or_memory());
|
VERIFY(dst.is_register_or_memory() || dst.type == Operand::Type::FReg);
|
||||||
VERIFY(src.type == Operand::Type::Reg);
|
VERIFY(src.type == Operand::Type::Reg || src.type == Operand::Type::FReg);
|
||||||
if (W == REX_W::No && to_underlying(dst.reg) < 8 && to_underlying(src.reg) < 8)
|
if (W == REX_W::No && to_underlying(dst.reg) < 8 && to_underlying(src.reg) < 8)
|
||||||
return;
|
return;
|
||||||
REX rex {
|
REX rex {
|
||||||
|
@ -254,8 +280,8 @@ struct X86_64Assembler {
|
||||||
|
|
||||||
void emit_rex_for_rm(Operand dst, Operand src, REX_W W)
|
void emit_rex_for_rm(Operand dst, Operand src, REX_W W)
|
||||||
{
|
{
|
||||||
VERIFY(src.is_register_or_memory());
|
VERIFY(src.is_register_or_memory() || src.type == Operand::Type::FReg);
|
||||||
VERIFY(dst.type == Operand::Type::Reg);
|
VERIFY(dst.type == Operand::Type::Reg || dst.type == Operand::Type::FReg);
|
||||||
if (W == REX_W::No && to_underlying(dst.reg) < 8 && to_underlying(src.reg) < 8)
|
if (W == REX_W::No && to_underlying(dst.reg) < 8 && to_underlying(src.reg) < 8)
|
||||||
return;
|
return;
|
||||||
REX rex {
|
REX rex {
|
||||||
|
@ -321,6 +347,24 @@ struct X86_64Assembler {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dst.type == Operand::Type::FReg && src.is_register_or_memory()) {
|
||||||
|
emit8(0x66);
|
||||||
|
emit_rex_for_rm(dst, src, REX_W::Yes);
|
||||||
|
emit8(0x0f);
|
||||||
|
emit8(0x6e);
|
||||||
|
emit_modrm_rm(dst, src, patchable);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dst.is_register_or_memory() && src.type == Operand::Type::FReg) {
|
||||||
|
emit8(0x66);
|
||||||
|
emit_rex_for_mr(dst, src, REX_W::Yes);
|
||||||
|
emit8(0x0f);
|
||||||
|
emit8(0x7e);
|
||||||
|
emit_modrm_mr(dst, src, patchable);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue