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,
|
dst,
|
||||||
srcloc,
|
srcloc,
|
||||||
} => {
|
} => {
|
||||||
let (opcodes, num_opcodes, rex_flags) = match ext_mode {
|
let (opcodes, num_opcodes, mut rex_flags) = match ext_mode {
|
||||||
ExtMode::BL => {
|
ExtMode::BL => {
|
||||||
// MOVZBL is (REX.W==0) 0F B6 /r
|
// MOVZBL is (REX.W==0) 0F B6 /r
|
||||||
(0x0FB6, 2, RexFlags::clear_w())
|
(0x0FB6, 2, RexFlags::clear_w())
|
||||||
@@ -847,15 +847,28 @@ pub(crate) fn emit(
|
|||||||
};
|
};
|
||||||
|
|
||||||
match src {
|
match src {
|
||||||
RegMem::Reg { reg: src } => emit_std_reg_reg(
|
RegMem::Reg { reg: src } => {
|
||||||
sink,
|
match ext_mode {
|
||||||
LegacyPrefix::None,
|
ExtMode::BL | ExtMode::BQ => {
|
||||||
opcodes,
|
// A redundant REX prefix must be emitted for certain register inputs.
|
||||||
num_opcodes,
|
let enc_src = int_reg_enc(*src);
|
||||||
dst.to_reg(),
|
if enc_src >= 4 && enc_src <= 7 {
|
||||||
*src,
|
rex_flags.always_emit();
|
||||||
rex_flags,
|
};
|
||||||
),
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
emit_std_reg_reg(
|
||||||
|
sink,
|
||||||
|
LegacyPrefix::None,
|
||||||
|
opcodes,
|
||||||
|
num_opcodes,
|
||||||
|
dst.to_reg(),
|
||||||
|
*src,
|
||||||
|
rex_flags,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
RegMem::Mem { addr: src } => {
|
RegMem::Mem { addr: src } => {
|
||||||
let src = &src.finalize(state);
|
let src = &src.finalize(state);
|
||||||
|
|
||||||
@@ -912,7 +925,7 @@ pub(crate) fn emit(
|
|||||||
dst,
|
dst,
|
||||||
srcloc,
|
srcloc,
|
||||||
} => {
|
} => {
|
||||||
let (opcodes, num_opcodes, rex_flags) = match ext_mode {
|
let (opcodes, num_opcodes, mut rex_flags) = match ext_mode {
|
||||||
ExtMode::BL => {
|
ExtMode::BL => {
|
||||||
// MOVSBL is (REX.W==0) 0F BE /r
|
// MOVSBL is (REX.W==0) 0F BE /r
|
||||||
(0x0FBE, 2, RexFlags::clear_w())
|
(0x0FBE, 2, RexFlags::clear_w())
|
||||||
@@ -936,15 +949,27 @@ pub(crate) fn emit(
|
|||||||
};
|
};
|
||||||
|
|
||||||
match src {
|
match src {
|
||||||
RegMem::Reg { reg: src } => emit_std_reg_reg(
|
RegMem::Reg { reg: src } => {
|
||||||
sink,
|
match ext_mode {
|
||||||
LegacyPrefix::None,
|
ExtMode::BL | ExtMode::BQ => {
|
||||||
opcodes,
|
// A redundant REX prefix must be emitted for certain register inputs.
|
||||||
num_opcodes,
|
let enc_src = int_reg_enc(*src);
|
||||||
dst.to_reg(),
|
if enc_src >= 4 && enc_src <= 7 {
|
||||||
*src,
|
rex_flags.always_emit();
|
||||||
rex_flags,
|
};
|
||||||
),
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
emit_std_reg_reg(
|
||||||
|
sink,
|
||||||
|
LegacyPrefix::None,
|
||||||
|
opcodes,
|
||||||
|
num_opcodes,
|
||||||
|
dst.to_reg(),
|
||||||
|
*src,
|
||||||
|
rex_flags,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
RegMem::Mem { addr: src } => {
|
RegMem::Mem { addr: src } => {
|
||||||
let src = &src.finalize(state);
|
let src = &src.finalize(state);
|
||||||
|
|||||||
@@ -1401,6 +1401,11 @@ fn test_x64_emit() {
|
|||||||
|
|
||||||
// ========================================================
|
// ========================================================
|
||||||
// MovZX_RM_R
|
// MovZX_RM_R
|
||||||
|
insns.push((
|
||||||
|
Inst::movzx_rm_r(ExtMode::BL, RegMem::reg(rdi), w_rdi, None),
|
||||||
|
"400FB6FF",
|
||||||
|
"movzbl %dil, %edi",
|
||||||
|
));
|
||||||
insns.push((
|
insns.push((
|
||||||
Inst::movzx_rm_r(ExtMode::BL, RegMem::reg(rax), w_rsi, None),
|
Inst::movzx_rm_r(ExtMode::BL, RegMem::reg(rax), w_rsi, None),
|
||||||
"0FB6F0",
|
"0FB6F0",
|
||||||
@@ -1723,6 +1728,11 @@ fn test_x64_emit() {
|
|||||||
|
|
||||||
// ========================================================
|
// ========================================================
|
||||||
// MovSX_RM_R
|
// MovSX_RM_R
|
||||||
|
insns.push((
|
||||||
|
Inst::movsx_rm_r(ExtMode::BL, RegMem::reg(rdi), w_rdi, None),
|
||||||
|
"400FBEFF",
|
||||||
|
"movsbl %dil, %edi",
|
||||||
|
));
|
||||||
insns.push((
|
insns.push((
|
||||||
Inst::movsx_rm_r(ExtMode::BL, RegMem::reg(rcx), w_rsi, None),
|
Inst::movsx_rm_r(ExtMode::BL, RegMem::reg(rcx), w_rsi, None),
|
||||||
"0FBEF1",
|
"0FBEF1",
|
||||||
|
|||||||
Reference in New Issue
Block a user