Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 40 additions & 27 deletions cranelift/codegen/src/isa/x64/encoding/rex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,18 +312,50 @@ pub(crate) fn emit_std_enc_mem(

prefixes.emit(sink);

// After prefixes, first emit the REX byte depending on the kind of
// addressing mode that's being used.
match *mem_e {
Amode::ImmReg { simm32, base, .. } => {
// First, the REX byte.
Amode::ImmReg { base, .. } => {
let enc_e = int_reg_enc(base);
rex.emit_two_op(sink, enc_g, enc_e);
}

// Now the opcode(s). These include any other prefixes the caller
// hands to us.
while num_opcodes > 0 {
num_opcodes -= 1;
sink.put1(((opcodes >> (num_opcodes << 3)) & 0xFF) as u8);
}
Amode::ImmRegRegShift {
base: reg_base,
index: reg_index,
..
} => {
let enc_base = int_reg_enc(*reg_base);
let enc_index = int_reg_enc(*reg_index);
rex.emit_three_op(sink, enc_g, enc_index, enc_base);
}

Amode::RipRelative { .. } => {
// note REX.B = 0.
rex.emit_two_op(sink, enc_g, 0);
}
}

// Now the opcode(s). These include any other prefixes the caller
// hands to us.
while num_opcodes > 0 {
num_opcodes -= 1;
sink.put1(((opcodes >> (num_opcodes << 3)) & 0xFF) as u8);
}

// And finally encode the mod/rm bytes and all further information.
emit_modrm_sib_disp(sink, enc_g, mem_e, bytes_at_end)
}

pub(crate) fn emit_modrm_sib_disp(
sink: &mut MachBuffer<Inst>,
enc_g: u8,
mem_e: &Amode,
bytes_at_end: u8,
) {
match *mem_e {
Amode::ImmReg { simm32, base, .. } => {
let enc_e = int_reg_enc(base);

// Now the mod/rm and associated immediates. This is
// significantly complicated due to the multiple special cases.
Expand Down Expand Up @@ -377,15 +409,6 @@ pub(crate) fn emit_std_enc_mem(
let enc_base = int_reg_enc(*reg_base);
let enc_index = int_reg_enc(*reg_index);

// The rex byte.
rex.emit_three_op(sink, enc_g, enc_index, enc_base);

// All other prefixes and opcodes.
while num_opcodes > 0 {
num_opcodes -= 1;
sink.put1(((opcodes >> (num_opcodes << 3)) & 0xFF) as u8);
}

// modrm, SIB, immediates.
if low8_will_sign_extend_to_32(simm32) && enc_index != regs::ENC_RSP {
sink.put1(encode_modrm(1, enc_g & 7, 4));
Expand All @@ -401,16 +424,6 @@ pub(crate) fn emit_std_enc_mem(
}

Amode::RipRelative { ref target } => {
// First, the REX byte, with REX.B = 0.
rex.emit_two_op(sink, enc_g, 0);

// Now the opcode(s). These include any other prefixes the caller
// hands to us.
while num_opcodes > 0 {
num_opcodes -= 1;
sink.put1(((opcodes >> (num_opcodes << 3)) & 0xFF) as u8);
}

// RIP-relative is mod=00, rm=101.
sink.put1(encode_modrm(0, enc_g & 7, 0b101));

Expand Down
Loading