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:
@@ -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,7 +847,18 @@ pub(crate) fn emit(
|
||||
};
|
||||
|
||||
match src {
|
||||
RegMem::Reg { reg: src } => emit_std_reg_reg(
|
||||
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,
|
||||
@@ -855,7 +866,9 @@ pub(crate) fn emit(
|
||||
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,7 +949,18 @@ pub(crate) fn emit(
|
||||
};
|
||||
|
||||
match src {
|
||||
RegMem::Reg { reg: src } => emit_std_reg_reg(
|
||||
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,
|
||||
@@ -944,7 +968,8 @@ pub(crate) fn emit(
|
||||
dst.to_reg(),
|
||||
*src,
|
||||
rex_flags,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
RegMem::Mem { addr: src } => {
|
||||
let src = &src.finalize(state);
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user