machinst x64: fix encoding of movzx/movsx with non-ABCD input registers;

Using an input register that doesn't belong to the ABCD family (al,
etc.) as the source of movsx/movzx requires a redundant REX prefix, that
was not emitted.
This commit is contained in:
Benjamin Bouvier
2020-07-23 14:12:12 +02:00
parent de4923356a
commit 2e3ad3227d
2 changed files with 55 additions and 20 deletions

View File

@@ -815,7 +815,7 @@ pub(crate) fn emit(
dst,
srcloc,
} => {
let (opcodes, num_opcodes, rex_flags) = match ext_mode {
let (opcodes, num_opcodes, mut rex_flags) = match ext_mode {
ExtMode::BL => {
// MOVZBL is (REX.W==0) 0F B6 /r
(0x0FB6, 2, RexFlags::clear_w())
@@ -847,15 +847,28 @@ pub(crate) fn emit(
};
match src {
RegMem::Reg { reg: src } => emit_std_reg_reg(
sink,
LegacyPrefix::None,
opcodes,
num_opcodes,
dst.to_reg(),
*src,
rex_flags,
),
RegMem::Reg { reg: src } => {
match ext_mode {
ExtMode::BL | ExtMode::BQ => {
// A redundant REX prefix must be emitted for certain register inputs.
let enc_src = int_reg_enc(*src);
if enc_src >= 4 && enc_src <= 7 {
rex_flags.always_emit();
};
}
_ => {}
}
emit_std_reg_reg(
sink,
LegacyPrefix::None,
opcodes,
num_opcodes,
dst.to_reg(),
*src,
rex_flags,
)
}
RegMem::Mem { addr: src } => {
let src = &src.finalize(state);
@@ -912,7 +925,7 @@ pub(crate) fn emit(
dst,
srcloc,
} => {
let (opcodes, num_opcodes, rex_flags) = match ext_mode {
let (opcodes, num_opcodes, mut rex_flags) = match ext_mode {
ExtMode::BL => {
// MOVSBL is (REX.W==0) 0F BE /r
(0x0FBE, 2, RexFlags::clear_w())
@@ -936,15 +949,27 @@ pub(crate) fn emit(
};
match src {
RegMem::Reg { reg: src } => emit_std_reg_reg(
sink,
LegacyPrefix::None,
opcodes,
num_opcodes,
dst.to_reg(),
*src,
rex_flags,
),
RegMem::Reg { reg: src } => {
match ext_mode {
ExtMode::BL | ExtMode::BQ => {
// A redundant REX prefix must be emitted for certain register inputs.
let enc_src = int_reg_enc(*src);
if enc_src >= 4 && enc_src <= 7 {
rex_flags.always_emit();
};
}
_ => {}
}
emit_std_reg_reg(
sink,
LegacyPrefix::None,
opcodes,
num_opcodes,
dst.to_reg(),
*src,
rex_flags,
)
}
RegMem::Mem { addr: src } => {
let src = &src.finalize(state);

View File

@@ -1401,6 +1401,11 @@ fn test_x64_emit() {
// ========================================================
// MovZX_RM_R
insns.push((
Inst::movzx_rm_r(ExtMode::BL, RegMem::reg(rdi), w_rdi, None),
"400FB6FF",
"movzbl %dil, %edi",
));
insns.push((
Inst::movzx_rm_r(ExtMode::BL, RegMem::reg(rax), w_rsi, None),
"0FB6F0",
@@ -1723,6 +1728,11 @@ fn test_x64_emit() {
// ========================================================
// MovSX_RM_R
insns.push((
Inst::movsx_rm_r(ExtMode::BL, RegMem::reg(rdi), w_rdi, None),
"400FBEFF",
"movsbl %dil, %edi",
));
insns.push((
Inst::movsx_rm_r(ExtMode::BL, RegMem::reg(rcx), w_rsi, None),
"0FBEF1",