mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 07:37:46 +00:00
LibJIT: Use ModRM helpers where applicable
This also widens the argument coverage of some helpers, to allow memory offsets, this also consolidates the displacement size choosing. This also stops us from some out argument ordering bugs, as we now just need to look up the correct calling convention and call the correct function.
This commit is contained in:
parent
b46c5545f1
commit
540963fbe3
1 changed files with 52 additions and 76 deletions
|
@ -77,6 +77,11 @@ struct Assembler {
|
||||||
return operand;
|
return operand;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_register_or_memory() const
|
||||||
|
{
|
||||||
|
return type == Type::Reg || type == Type::Mem64BaseAndOffset;
|
||||||
|
}
|
||||||
|
|
||||||
bool fits_in_u8() const
|
bool fits_in_u8() const
|
||||||
{
|
{
|
||||||
VERIFY(type == Type::Imm);
|
VERIFY(type == Type::Imm);
|
||||||
|
@ -204,20 +209,20 @@ struct Assembler {
|
||||||
VERIFY(count.fits_in_u8());
|
VERIFY(count.fits_in_u8());
|
||||||
emit8(0x48 | ((to_underlying(dst.reg) >= 8) ? 1 << 0 : 0));
|
emit8(0x48 | ((to_underlying(dst.reg) >= 8) ? 1 << 0 : 0));
|
||||||
emit8(0xc1);
|
emit8(0xc1);
|
||||||
emit8(0xe8 | encode_reg(dst.reg));
|
emit_modrm_slash(5, dst);
|
||||||
emit8(count.offset_or_immediate);
|
emit8(count.offset_or_immediate);
|
||||||
}
|
}
|
||||||
|
|
||||||
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.is_register_or_memory() && src.type == Operand::Type::Reg) {
|
||||||
if (src.reg == dst.reg)
|
if (src.type == Operand::Type::Reg && src.reg == dst.reg)
|
||||||
return;
|
return;
|
||||||
emit8(0x48
|
emit8(0x48
|
||||||
| ((to_underlying(src.reg) >= 8) ? 1 << 2 : 0)
|
| ((to_underlying(src.reg) >= 8) ? 1 << 2 : 0)
|
||||||
| ((to_underlying(dst.reg) >= 8) ? 1 << 0 : 0));
|
| ((to_underlying(dst.reg) >= 8) ? 1 << 0 : 0));
|
||||||
emit8(0x89);
|
emit8(0x89);
|
||||||
emit8(0xc0 | (encode_reg(src.reg) << 3) | encode_reg(dst.reg));
|
emit_modrm_mr(dst, src, patchable);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,7 +232,7 @@ struct Assembler {
|
||||||
// xor dst, dst
|
// xor dst, dst
|
||||||
emit8(0x48 | ((to_underlying(dst.reg) >= 8) ? (1 << 0 | 1 << 2) : 0));
|
emit8(0x48 | ((to_underlying(dst.reg) >= 8) ? (1 << 0 | 1 << 2) : 0));
|
||||||
emit8(0x31);
|
emit8(0x31);
|
||||||
emit8(0xc0 | (encode_reg(dst.reg) << 3) | encode_reg(dst.reg));
|
emit_modrm_mr(dst, dst, patchable);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (src.fits_in_u32()) {
|
if (src.fits_in_u32()) {
|
||||||
|
@ -244,37 +249,12 @@ struct Assembler {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dst.type == Operand::Type::Mem64BaseAndOffset && src.type == Operand::Type::Reg) {
|
if (dst.type == Operand::Type::Reg && src.is_register_or_memory()) {
|
||||||
emit8(0x48
|
|
||||||
| ((to_underlying(src.reg) >= 8) ? 1 << 2 : 0)
|
|
||||||
| ((to_underlying(dst.reg) >= 8) ? 1 << 0 : 0));
|
|
||||||
emit8(0x89);
|
|
||||||
if (dst.reg <= Reg::RDI && dst.offset_or_immediate == 0) {
|
|
||||||
emit8(0x00 | (encode_reg(src.reg) << 3) | encode_reg(dst.reg));
|
|
||||||
} else if (dst.offset_or_immediate <= 127) {
|
|
||||||
emit8(0x40 | (encode_reg(src.reg) << 3) | encode_reg(dst.reg));
|
|
||||||
emit8(dst.offset_or_immediate);
|
|
||||||
} else {
|
|
||||||
emit8(0x80 | (encode_reg(src.reg) << 3) | encode_reg(dst.reg));
|
|
||||||
emit32(dst.offset_or_immediate);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dst.type == Operand::Type::Reg && src.type == Operand::Type::Mem64BaseAndOffset) {
|
|
||||||
emit8(0x48
|
emit8(0x48
|
||||||
| ((to_underlying(dst.reg) >= 8) ? 1 << 2 : 0)
|
| ((to_underlying(dst.reg) >= 8) ? 1 << 2 : 0)
|
||||||
| ((to_underlying(src.reg) >= 8) ? 1 << 0 : 0));
|
| ((to_underlying(src.reg) >= 8) ? 1 << 0 : 0));
|
||||||
emit8(0x8b);
|
emit8(0x8b);
|
||||||
if (src.reg <= Reg::RDI && src.offset_or_immediate == 0) {
|
emit_modrm_rm(dst, src, patchable);
|
||||||
emit8(0x00 | (encode_reg(dst.reg) << 3) | encode_reg(src.reg));
|
|
||||||
} else if (src.offset_or_immediate <= 127) {
|
|
||||||
emit8(0x40 | (encode_reg(dst.reg) << 3) | encode_reg(src.reg));
|
|
||||||
emit8(src.offset_or_immediate);
|
|
||||||
} else {
|
|
||||||
emit8(0x80 | (encode_reg(dst.reg) << 3) | encode_reg(src.reg));
|
|
||||||
emit32(src.offset_or_immediate);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,14 +342,10 @@ struct Assembler {
|
||||||
|
|
||||||
void jump(Operand op)
|
void jump(Operand op)
|
||||||
{
|
{
|
||||||
if (op.type == Operand::Type::Reg) {
|
if (to_underlying(op.reg) >= 8)
|
||||||
if (to_underlying(op.reg) >= 8)
|
emit8(0x41);
|
||||||
emit8(0x41);
|
emit8(0xff);
|
||||||
emit8(0xff);
|
emit_modrm_slash(4, op);
|
||||||
emit8(0xe0 | encode_reg(op.reg));
|
|
||||||
} else {
|
|
||||||
VERIFY_NOT_REACHED();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void verify_not_reached()
|
void verify_not_reached()
|
||||||
|
@ -381,23 +357,23 @@ struct Assembler {
|
||||||
|
|
||||||
void cmp(Operand lhs, Operand rhs)
|
void cmp(Operand lhs, Operand rhs)
|
||||||
{
|
{
|
||||||
if (rhs.type == Operand::Type::Imm && rhs.offset_or_immediate == 0) {
|
if (lhs.type == Operand::Type::Reg && rhs.type == Operand::Type::Imm && rhs.offset_or_immediate == 0) {
|
||||||
test(lhs, lhs);
|
test(lhs, lhs);
|
||||||
} else if (lhs.type == Operand::Type::Reg && rhs.type == Operand::Type::Reg) {
|
} else if (lhs.is_register_or_memory() && rhs.type == Operand::Type::Reg) {
|
||||||
emit8(0x48
|
emit8(0x48
|
||||||
| ((to_underlying(rhs.reg) >= 8) ? 1 << 2 : 0)
|
| ((to_underlying(rhs.reg) >= 8) ? 1 << 2 : 0)
|
||||||
| ((to_underlying(lhs.reg) >= 8) ? 1 << 0 : 0));
|
| ((to_underlying(lhs.reg) >= 8) ? 1 << 0 : 0));
|
||||||
emit8(0x39);
|
emit8(0x39);
|
||||||
emit8(0xc0 | (encode_reg(rhs.reg) << 3) | encode_reg(lhs.reg));
|
emit_modrm_mr(lhs, rhs);
|
||||||
} else if (lhs.type == Operand::Type::Reg && rhs.type == Operand::Type::Imm && rhs.fits_in_i8()) {
|
} else if (lhs.is_register_or_memory() && rhs.type == Operand::Type::Imm && rhs.fits_in_i8()) {
|
||||||
emit8(0x48 | ((to_underlying(lhs.reg) >= 8) ? 1 << 0 : 0));
|
emit8(0x48 | ((to_underlying(lhs.reg) >= 8) ? 1 << 0 : 0));
|
||||||
emit8(0x83);
|
emit8(0x83);
|
||||||
emit8(0xf8 | encode_reg(lhs.reg));
|
emit_modrm_slash(7, lhs);
|
||||||
emit8(rhs.offset_or_immediate);
|
emit8(rhs.offset_or_immediate);
|
||||||
} else if (lhs.type == Operand::Type::Reg && rhs.type == Operand::Type::Imm && rhs.fits_in_i32()) {
|
} else if (lhs.is_register_or_memory() && rhs.type == Operand::Type::Imm && rhs.fits_in_i32()) {
|
||||||
emit8(0x48 | ((to_underlying(lhs.reg) >= 8) ? 1 << 0 : 0));
|
emit8(0x48 | ((to_underlying(lhs.reg) >= 8) ? 1 << 0 : 0));
|
||||||
emit8(0x81);
|
emit8(0x81);
|
||||||
emit8(0xf8 | encode_reg(lhs.reg));
|
emit_modrm_slash(7, lhs);
|
||||||
emit32(rhs.offset_or_immediate);
|
emit32(rhs.offset_or_immediate);
|
||||||
} else {
|
} else {
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
|
@ -406,17 +382,17 @@ struct Assembler {
|
||||||
|
|
||||||
void test(Operand lhs, Operand rhs)
|
void test(Operand lhs, Operand rhs)
|
||||||
{
|
{
|
||||||
if (lhs.type == Operand::Type::Reg && rhs.type == Operand::Type::Reg) {
|
if (lhs.is_register_or_memory() && rhs.type == Operand::Type::Reg) {
|
||||||
emit8(0x48
|
emit8(0x48
|
||||||
| ((to_underlying(rhs.reg) >= 8) ? 1 << 2 : 0)
|
| ((to_underlying(rhs.reg) >= 8) ? 1 << 2 : 0)
|
||||||
| ((to_underlying(lhs.reg) >= 8) ? 1 << 0 : 0));
|
| ((to_underlying(lhs.reg) >= 8) ? 1 << 0 : 0));
|
||||||
emit8(0x85);
|
emit8(0x85);
|
||||||
emit8(0xc0 | (encode_reg(rhs.reg) << 3) | encode_reg(lhs.reg));
|
emit_modrm_mr(lhs, rhs);
|
||||||
} else if (lhs.type == Operand::Type::Reg && rhs.type == Operand::Type::Imm) {
|
} else if (lhs.type != Operand::Type::Imm && rhs.type == Operand::Type::Imm) {
|
||||||
VERIFY(rhs.fits_in_i32());
|
VERIFY(rhs.fits_in_i32());
|
||||||
emit8(0x48 | ((to_underlying(lhs.reg) >= 8) ? 1 << 0 : 0));
|
emit8(0x48 | ((to_underlying(lhs.reg) >= 8) ? 1 << 0 : 0));
|
||||||
emit8(0xf7);
|
emit8(0xf7);
|
||||||
emit8(0xc0 | encode_reg(lhs.reg));
|
emit_modrm_slash(0, lhs);
|
||||||
emit32(rhs.offset_or_immediate);
|
emit32(rhs.offset_or_immediate);
|
||||||
} else {
|
} else {
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
|
@ -438,27 +414,27 @@ struct Assembler {
|
||||||
// movsxd (reg as 64-bit), (reg as 32-bit)
|
// movsxd (reg as 64-bit), (reg as 32-bit)
|
||||||
emit8(0x48 | ((to_underlying(reg) >= 8) ? 1 << 0 : 0));
|
emit8(0x48 | ((to_underlying(reg) >= 8) ? 1 << 0 : 0));
|
||||||
emit8(0x63);
|
emit8(0x63);
|
||||||
emit8(0xc0 | (encode_reg(reg) << 3) | encode_reg(reg));
|
emit_modrm_rm(Operand::Register(reg), Operand::Register(reg));
|
||||||
}
|
}
|
||||||
|
|
||||||
void bitwise_and(Operand dst, Operand src)
|
void bitwise_and(Operand dst, Operand src)
|
||||||
{
|
{
|
||||||
// and dst,src
|
// and dst,src
|
||||||
if (dst.type == Operand::Type::Reg && src.type == Operand::Type::Reg) {
|
if (dst.is_register_or_memory() && src.type == Operand::Type::Reg) {
|
||||||
emit8(0x48
|
emit8(0x48
|
||||||
| ((to_underlying(src.reg) >= 8) ? 1 << 2 : 0)
|
| ((to_underlying(src.reg) >= 8) ? 1 << 2 : 0)
|
||||||
| ((to_underlying(dst.reg) >= 8) ? 1 << 0 : 0));
|
| ((to_underlying(dst.reg) >= 8) ? 1 << 0 : 0));
|
||||||
emit8(0x21);
|
emit8(0x21);
|
||||||
emit8(0xc0 | (encode_reg(src.reg) << 3) | encode_reg(dst.reg));
|
emit_modrm_mr(dst, src);
|
||||||
} else if (dst.type == Operand::Type::Reg && src.type == Operand::Type::Imm && src.fits_in_i8()) {
|
} else if (dst.type == Operand::Type::Reg && src.type == Operand::Type::Imm && src.fits_in_i8()) {
|
||||||
emit8(0x48 | ((to_underlying(dst.reg) >= 8) ? 1 << 0 : 0));
|
emit8(0x48 | ((to_underlying(dst.reg) >= 8) ? 1 << 0 : 0));
|
||||||
emit8(0x83);
|
emit8(0x83);
|
||||||
emit8(0xe0 | encode_reg(dst.reg));
|
emit_modrm_slash(4, dst);
|
||||||
emit8(src.offset_or_immediate);
|
emit8(src.offset_or_immediate);
|
||||||
} else if (dst.type == Operand::Type::Reg && src.type == Operand::Type::Imm && src.fits_in_i32()) {
|
} else if (dst.type == Operand::Type::Reg && src.type == Operand::Type::Imm && src.fits_in_i32()) {
|
||||||
emit8(0x48 | ((to_underlying(dst.reg) >= 8) ? 1 << 0 : 0));
|
emit8(0x48 | ((to_underlying(dst.reg) >= 8) ? 1 << 0 : 0));
|
||||||
emit8(0x81);
|
emit8(0x81);
|
||||||
emit8(0xe0 | encode_reg(dst.reg));
|
emit_modrm_slash(4, dst);
|
||||||
emit32(src.offset_or_immediate);
|
emit32(src.offset_or_immediate);
|
||||||
} else {
|
} else {
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
|
@ -468,21 +444,21 @@ struct Assembler {
|
||||||
void bitwise_or(Operand dst, Operand src)
|
void bitwise_or(Operand dst, Operand src)
|
||||||
{
|
{
|
||||||
// or dst,src
|
// or dst,src
|
||||||
if (dst.type == Operand::Type::Reg && src.type == Operand::Type::Reg) {
|
if (dst.is_register_or_memory() && src.type == Operand::Type::Reg) {
|
||||||
emit8(0x48
|
emit8(0x48
|
||||||
| ((to_underlying(src.reg) >= 8) ? 1 << 2 : 0)
|
| ((to_underlying(src.reg) >= 8) ? 1 << 2 : 0)
|
||||||
| ((to_underlying(dst.reg) >= 8) ? 1 << 0 : 0));
|
| ((to_underlying(dst.reg) >= 8) ? 1 << 0 : 0));
|
||||||
emit8(0x09);
|
emit8(0x09);
|
||||||
emit8(0xc0 | (encode_reg(src.reg) << 3) | encode_reg(dst.reg));
|
emit_modrm_mr(dst, src);
|
||||||
} else if (dst.type == Operand::Type::Reg && src.type == Operand::Type::Imm && src.fits_in_i8()) {
|
} else if (dst.type == Operand::Type::Reg && src.type == Operand::Type::Imm && src.fits_in_i8()) {
|
||||||
emit8(0x48 | ((to_underlying(dst.reg) >= 8) ? 1 << 0 : 0));
|
emit8(0x48 | ((to_underlying(dst.reg) >= 8) ? 1 << 0 : 0));
|
||||||
emit8(0x83);
|
emit8(0x83);
|
||||||
emit8(0xc8 | encode_reg(dst.reg));
|
emit_modrm_slash(1, dst);
|
||||||
emit8(src.offset_or_immediate);
|
emit8(src.offset_or_immediate);
|
||||||
} else if (dst.type == Operand::Type::Reg && src.type == Operand::Type::Imm && src.fits_in_i32()) {
|
} else if (dst.type == Operand::Type::Reg && src.type == Operand::Type::Imm && src.fits_in_i32()) {
|
||||||
emit8(0x48 | ((to_underlying(dst.reg) >= 8) ? 1 << 0 : 0));
|
emit8(0x48 | ((to_underlying(dst.reg) >= 8) ? 1 << 0 : 0));
|
||||||
emit8(0x81);
|
emit8(0x81);
|
||||||
emit8(0xc8 | encode_reg(dst.reg));
|
emit_modrm_slash(1, dst);
|
||||||
emit32(src.offset_or_immediate);
|
emit32(src.offset_or_immediate);
|
||||||
} else {
|
} else {
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
|
@ -565,21 +541,21 @@ struct Assembler {
|
||||||
|
|
||||||
void add(Operand dst, Operand src)
|
void add(Operand dst, Operand src)
|
||||||
{
|
{
|
||||||
if (dst.type == Operand::Type::Reg && src.type == Operand::Type::Reg) {
|
if (dst.is_register_or_memory() && src.type == Operand::Type::Reg) {
|
||||||
emit8(0x48
|
emit8(0x48
|
||||||
| ((to_underlying(src.reg) >= 8) ? 1 << 2 : 0)
|
| ((to_underlying(src.reg) >= 8) ? 1 << 2 : 0)
|
||||||
| ((to_underlying(dst.reg) >= 8) ? 1 << 0 : 0));
|
| ((to_underlying(dst.reg) >= 8) ? 1 << 0 : 0));
|
||||||
emit8(0x01);
|
emit8(0x01);
|
||||||
emit8(0xc0 | (encode_reg(src.reg) << 3) | encode_reg(dst.reg));
|
emit_modrm_mr(dst, src);
|
||||||
} else if (dst.type == Operand::Type::Reg && src.type == Operand::Type::Imm && src.fits_in_i8()) {
|
} else if (dst.is_register_or_memory() && src.type == Operand::Type::Imm && src.fits_in_i8()) {
|
||||||
emit8(0x48 | ((to_underlying(dst.reg) >= 8) ? 1 << 0 : 0));
|
emit8(0x48 | ((to_underlying(dst.reg) >= 8) ? 1 << 0 : 0));
|
||||||
emit8(0x83);
|
emit8(0x83);
|
||||||
emit8(0xc0 | encode_reg(dst.reg));
|
emit_modrm_slash(0, dst);
|
||||||
emit8(src.offset_or_immediate);
|
emit8(src.offset_or_immediate);
|
||||||
} else if (dst.type == Operand::Type::Reg && src.type == Operand::Type::Imm && src.fits_in_i32()) {
|
} else if (dst.is_register_or_memory() && src.type == Operand::Type::Imm && src.fits_in_i32()) {
|
||||||
emit8(0x48 | ((to_underlying(dst.reg) >= 8) ? 1 << 0 : 0));
|
emit8(0x48 | ((to_underlying(dst.reg) >= 8) ? 1 << 0 : 0));
|
||||||
emit8(0x81);
|
emit8(0x81);
|
||||||
emit8(0xc0 | encode_reg(dst.reg));
|
emit_modrm_slash(0, dst);
|
||||||
emit32(src.offset_or_immediate);
|
emit32(src.offset_or_immediate);
|
||||||
} else {
|
} else {
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
|
@ -590,14 +566,14 @@ struct Assembler {
|
||||||
{
|
{
|
||||||
if (dst.type == Operand::Type::Reg && to_underlying(dst.reg) < 8 && src.type == Operand::Type::Reg && to_underlying(src.reg) < 8) {
|
if (dst.type == Operand::Type::Reg && to_underlying(dst.reg) < 8 && src.type == Operand::Type::Reg && to_underlying(src.reg) < 8) {
|
||||||
emit8(0x01);
|
emit8(0x01);
|
||||||
emit8(0xc0 | (encode_reg(src.reg) << 3) | encode_reg(dst.reg));
|
emit_modrm_mr(dst, src);
|
||||||
} else if (dst.type == Operand::Type::Reg && to_underlying(dst.reg) < 8 && src.type == Operand::Type::Imm && src.fits_in_i8()) {
|
} else if (dst.type == Operand::Type::Reg && to_underlying(dst.reg) < 8 && src.type == Operand::Type::Imm && src.fits_in_i8()) {
|
||||||
emit8(0x83);
|
emit8(0x83);
|
||||||
emit8(0xc0 | encode_reg(dst.reg));
|
emit_modrm_slash(0, dst);
|
||||||
emit8(src.offset_or_immediate);
|
emit8(src.offset_or_immediate);
|
||||||
} else if (dst.type == Operand::Type::Reg && to_underlying(dst.reg) < 8 && src.type == Operand::Type::Imm && src.fits_in_i32()) {
|
} else if (dst.type == Operand::Type::Reg && to_underlying(dst.reg) < 8 && src.type == Operand::Type::Imm && src.fits_in_i32()) {
|
||||||
emit8(0x81);
|
emit8(0x81);
|
||||||
emit8(0xc0 | encode_reg(dst.reg));
|
emit_modrm_slash(0, dst);
|
||||||
emit32(src.offset_or_immediate);
|
emit32(src.offset_or_immediate);
|
||||||
} else {
|
} else {
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
|
@ -614,21 +590,21 @@ struct Assembler {
|
||||||
|
|
||||||
void sub(Operand dst, Operand src)
|
void sub(Operand dst, Operand src)
|
||||||
{
|
{
|
||||||
if (dst.type == Operand::Type::Reg && src.type == Operand::Type::Reg) {
|
if (dst.is_register_or_memory() && src.type == Operand::Type::Reg) {
|
||||||
emit8(0x48
|
emit8(0x48
|
||||||
| ((to_underlying(src.reg) >= 8) ? 1 << 2 : 0)
|
| ((to_underlying(src.reg) >= 8) ? 1 << 2 : 0)
|
||||||
| ((to_underlying(dst.reg) >= 8) ? 1 << 0 : 0));
|
| ((to_underlying(dst.reg) >= 8) ? 1 << 0 : 0));
|
||||||
emit8(0x29);
|
emit8(0x29);
|
||||||
emit8(0xc0 | (encode_reg(src.reg) << 3) | encode_reg(dst.reg));
|
emit_modrm_mr(dst, src);
|
||||||
} else if (dst.type == Operand::Type::Reg && src.type == Operand::Type::Imm && src.fits_in_i8()) {
|
} else if (dst.is_register_or_memory() && src.type == Operand::Type::Imm && src.fits_in_i8()) {
|
||||||
emit8(0x48 | ((to_underlying(dst.reg) >= 8) ? 1 << 0 : 0));
|
emit8(0x48 | ((to_underlying(dst.reg) >= 8) ? 1 << 0 : 0));
|
||||||
emit8(0x83);
|
emit8(0x83);
|
||||||
emit8(0xe8 | encode_reg(dst.reg));
|
emit_modrm_slash(5, dst);
|
||||||
emit8(src.offset_or_immediate);
|
emit8(src.offset_or_immediate);
|
||||||
} else if (dst.type == Operand::Type::Reg && src.type == Operand::Type::Imm && src.fits_in_i32()) {
|
} else if (dst.is_register_or_memory() && src.type == Operand::Type::Imm && src.fits_in_i32()) {
|
||||||
emit8(0x48 | ((to_underlying(dst.reg) >= 8) ? 1 << 0 : 0));
|
emit8(0x48 | ((to_underlying(dst.reg) >= 8) ? 1 << 0 : 0));
|
||||||
emit8(0x81);
|
emit8(0x81);
|
||||||
emit8(0xe8 | encode_reg(dst.reg));
|
emit_modrm_slash(5, dst);
|
||||||
emit32(src.offset_or_immediate);
|
emit32(src.offset_or_immediate);
|
||||||
} else {
|
} else {
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
|
@ -649,7 +625,7 @@ struct Assembler {
|
||||||
|
|
||||||
// call RAX
|
// call RAX
|
||||||
emit8(0xff);
|
emit8(0xff);
|
||||||
emit8(0xd0);
|
emit_modrm_slash(2, Operand::Register(Reg::RAX));
|
||||||
|
|
||||||
if (!stack_arguments.is_empty())
|
if (!stack_arguments.is_empty())
|
||||||
add(Operand::Register(Reg::RSP), Operand::Imm(align_up_to(stack_arguments.size(), 2) * sizeof(void*)));
|
add(Operand::Register(Reg::RSP), Operand::Imm(align_up_to(stack_arguments.size(), 2) * sizeof(void*)));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue