mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 06:14:46 +00:00
move with sign extension
This commit is contained in:
parent
0bf3eefbf2
commit
5363b95c5f
4 changed files with 59 additions and 52 deletions
|
@ -769,7 +769,6 @@ impl Assembler<AArch64GeneralReg, AArch64FloatReg> for AArch64Assembler {
|
|||
fn movsx_reg_reg(
|
||||
_buf: &mut Vec<'_, u8>,
|
||||
_input_width: RegisterWidth,
|
||||
_output_width: RegisterWidth,
|
||||
_dst: AArch64GeneralReg,
|
||||
_src: AArch64GeneralReg,
|
||||
) {
|
||||
|
|
|
@ -292,7 +292,6 @@ pub trait Assembler<GeneralReg: RegTrait, FloatReg: RegTrait>: Sized + Copy {
|
|||
fn movsx_reg_reg(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
input_width: RegisterWidth,
|
||||
output_width: RegisterWidth,
|
||||
dst: GeneralReg,
|
||||
src: GeneralReg,
|
||||
);
|
||||
|
@ -2998,18 +2997,10 @@ impl<
|
|||
ASM::mov_reg_reg(buf, RegisterWidth::W32, dst_reg, src_reg);
|
||||
}
|
||||
(I8, I16 | I32 | I64) => {
|
||||
// zero out the register
|
||||
ASM::xor_reg64_reg64_reg64(buf, dst_reg, dst_reg, dst_reg);
|
||||
|
||||
// move the 8-bit integer
|
||||
ASM::movsx_reg_reg(
|
||||
buf,
|
||||
RegisterWidth::W8,
|
||||
RegisterWidth::W16,
|
||||
dst_reg,
|
||||
src_reg,
|
||||
);
|
||||
ASM::movsx_reg_reg(buf, RegisterWidth::W8, dst_reg, src_reg)
|
||||
}
|
||||
(I16, I32 | I64) => ASM::movsx_reg_reg(buf, RegisterWidth::W16, dst_reg, src_reg),
|
||||
(I32, I64) => ASM::movsx_reg_reg(buf, RegisterWidth::W32, dst_reg, src_reg),
|
||||
// -- CASTING DOWN --
|
||||
(U64 | I64, I32 | U32) => {
|
||||
// move as a 32-bit integer (leaving any other bits behind)
|
||||
|
|
|
@ -1494,11 +1494,10 @@ impl Assembler<X86_64GeneralReg, X86_64FloatReg> for X86_64Assembler {
|
|||
fn movsx_reg_reg(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
input_width: RegisterWidth,
|
||||
output_width: RegisterWidth,
|
||||
dst: X86_64GeneralReg,
|
||||
src: X86_64GeneralReg,
|
||||
) {
|
||||
raw_movsx_reg_reg(buf, input_width, output_width, dst, src);
|
||||
raw_movsx_reg_reg(buf, input_width, dst, src);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -2564,46 +2563,31 @@ fn raw_mov_reg_reg(
|
|||
fn raw_movsx_reg_reg(
|
||||
buf: &mut Vec<u8>,
|
||||
input_width: RegisterWidth,
|
||||
output_width: RegisterWidth,
|
||||
dst: X86_64GeneralReg,
|
||||
src: X86_64GeneralReg,
|
||||
) {
|
||||
match (input_width, output_width) {
|
||||
(RegisterWidth::W8, RegisterWidth::W16) => {
|
||||
buf.push(0x0F);
|
||||
buf.push(0xBE);
|
||||
binop_reg8_reg8(0x89, buf, dst, src);
|
||||
let dst_high = dst as u8 > 7;
|
||||
let dst_mod = dst as u8 % 8;
|
||||
let src_high = src as u8 > 7;
|
||||
let src_mod = src as u8 % 8;
|
||||
|
||||
// NOTE src and dst seem to be flipped here. It works this way though
|
||||
let mod_rm = 0xC0 | (dst_mod << 3) | src_mod;
|
||||
|
||||
let rex = add_rm_extension(src, REX_W);
|
||||
let rex = add_reg_extension(dst, rex);
|
||||
|
||||
match input_width {
|
||||
RegisterWidth::W8 => {
|
||||
buf.extend([rex, 0x0f, 0xbe, mod_rm]);
|
||||
}
|
||||
(RegisterWidth::W8, RegisterWidth::W32) => {
|
||||
buf.push(0x0F);
|
||||
buf.push(0xBF);
|
||||
binop_reg8_reg8(0x89, buf, dst, src);
|
||||
RegisterWidth::W16 => {
|
||||
buf.extend([rex, 0x0f, 0xbf, mod_rm]);
|
||||
}
|
||||
(RegisterWidth::W8, RegisterWidth::W64) => {
|
||||
buf.push(0x48);
|
||||
buf.push(0x0F);
|
||||
buf.push(0xBE);
|
||||
binop_reg8_reg8(0x89, buf, dst, src);
|
||||
RegisterWidth::W32 => {
|
||||
buf.extend([rex, 0x63, mod_rm]);
|
||||
}
|
||||
(RegisterWidth::W16, RegisterWidth::W32) => {
|
||||
buf.push(0x66);
|
||||
buf.push(0x0F);
|
||||
buf.push(0xBF);
|
||||
binop_reg16_reg16(0x89, buf, dst, src);
|
||||
}
|
||||
(RegisterWidth::W16, RegisterWidth::W64) => {
|
||||
buf.push(0x48);
|
||||
buf.push(0x0F);
|
||||
buf.push(0xBF);
|
||||
binop_reg16_reg16(0x89, buf, dst, src);
|
||||
}
|
||||
(RegisterWidth::W32, RegisterWidth::W64) => {
|
||||
buf.push(0x48);
|
||||
buf.push(0x0F);
|
||||
buf.push(0xBF);
|
||||
binop_reg32_reg32(0x89, buf, dst, src);
|
||||
}
|
||||
_ => panic!("Invalid input/output register width combination"),
|
||||
RegisterWidth::W64 => { /* do nothing */ }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3694,6 +3678,36 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_movsx_reg64_reg64() {
|
||||
disassembler_test!(
|
||||
raw_movsx_reg_reg,
|
||||
|w, reg1, reg2| {
|
||||
match w {
|
||||
RegisterWidth::W8 => format!(
|
||||
"movsx {}, {}",
|
||||
reg1,
|
||||
X86_64GeneralReg::low_8bits_string(®2)
|
||||
),
|
||||
RegisterWidth::W16 => format!(
|
||||
"movsx {}, {}",
|
||||
reg1,
|
||||
X86_64GeneralReg::low_16bits_string(®2)
|
||||
),
|
||||
RegisterWidth::W32 => format!(
|
||||
"movsxd {}, {}",
|
||||
reg1,
|
||||
X86_64GeneralReg::low_32bits_string(®2)
|
||||
),
|
||||
RegisterWidth::W64 => String::new(),
|
||||
}
|
||||
},
|
||||
ALL_REGISTER_WIDTHS,
|
||||
ALL_GENERAL_REGS,
|
||||
ALL_GENERAL_REGS
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_movsd_freg64_base64_offset32() {
|
||||
disassembler_test!(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue