From 6a19009acf88a062bf08e400663f55b45d80a35f Mon Sep 17 00:00:00 2001 From: Folkert Date: Sun, 9 Jul 2023 15:41:41 +0200 Subject: [PATCH] 32-bit float mov instruction --- .../compiler/gen_dev/src/generic64/aarch64.rs | 4 ++ crates/compiler/gen_dev/src/generic64/mod.rs | 1 + .../compiler/gen_dev/src/generic64/storage.rs | 6 ++- .../compiler/gen_dev/src/generic64/x86_64.rs | 41 +++++++++++++++++++ 4 files changed, 51 insertions(+), 1 deletion(-) diff --git a/crates/compiler/gen_dev/src/generic64/aarch64.rs b/crates/compiler/gen_dev/src/generic64/aarch64.rs index 6f06abf661..24e09234ad 100644 --- a/crates/compiler/gen_dev/src/generic64/aarch64.rs +++ b/crates/compiler/gen_dev/src/generic64/aarch64.rs @@ -832,6 +832,10 @@ impl Assembler for AArch64Assembler { todo!("saving floating point reg to base offset for AArch64"); } #[inline(always)] + fn mov_base32_freg32(_buf: &mut Vec<'_, u8>, _offset: i32, _src: AArch64FloatReg) { + todo!("saving floating point reg to base offset for AArch64"); + } + #[inline(always)] fn movesd_mem64_offset32_freg64( _buf: &mut Vec<'_, u8>, _ptr: AArch64GeneralReg, diff --git a/crates/compiler/gen_dev/src/generic64/mod.rs b/crates/compiler/gen_dev/src/generic64/mod.rs index 68d850b63c..3226188760 100644 --- a/crates/compiler/gen_dev/src/generic64/mod.rs +++ b/crates/compiler/gen_dev/src/generic64/mod.rs @@ -321,6 +321,7 @@ pub trait Assembler: Sized + Copy { fn mov_reg8_base32(buf: &mut Vec<'_, u8>, dst: GeneralReg, offset: i32); fn mov_base32_freg64(buf: &mut Vec<'_, u8>, offset: i32, src: FloatReg); + fn mov_base32_freg32(buf: &mut Vec<'_, u8>, offset: i32, src: FloatReg); fn mov_base32_reg64(buf: &mut Vec<'_, u8>, offset: i32, src: GeneralReg); fn mov_base32_reg32(buf: &mut Vec<'_, u8>, offset: i32, src: GeneralReg); diff --git a/crates/compiler/gen_dev/src/generic64/storage.rs b/crates/compiler/gen_dev/src/generic64/storage.rs index 318f9dc0f6..6c053a1e33 100644 --- a/crates/compiler/gen_dev/src/generic64/storage.rs +++ b/crates/compiler/gen_dev/src/generic64/storage.rs @@ -783,7 +783,11 @@ impl< let reg = self.load_to_float_reg(buf, sym); ASM::mov_base32_freg64(buf, to_offset, reg); } - FloatWidth::F32 => todo!(), + FloatWidth::F32 => { + debug_assert_eq!(to_offset % 4, 0); + let reg = self.load_to_float_reg(buf, sym); + ASM::mov_base32_freg64(buf, to_offset, reg); + } }, Builtin::Bool => { // same as 8-bit integer, but we special-case true/false because these symbols diff --git a/crates/compiler/gen_dev/src/generic64/x86_64.rs b/crates/compiler/gen_dev/src/generic64/x86_64.rs index efeb6d8cce..3229967203 100644 --- a/crates/compiler/gen_dev/src/generic64/x86_64.rs +++ b/crates/compiler/gen_dev/src/generic64/x86_64.rs @@ -1584,6 +1584,11 @@ impl Assembler for X86_64Assembler { movsd_base64_offset32_freg64(buf, X86_64GeneralReg::RBP, offset, src) } + #[inline(always)] + fn mov_base32_freg32(buf: &mut Vec<'_, u8>, offset: i32, src: X86_64FloatReg) { + movss_base32_offset32_freg32(buf, X86_64GeneralReg::RBP, offset, src) + } + #[inline(always)] fn movesd_mem64_offset32_freg64( buf: &mut Vec<'_, u8>, @@ -3180,6 +3185,31 @@ fn movsd_base64_offset32_freg64( buf.extend(offset.to_le_bytes()); } +// `MOVSS r/m64,xmm1` -> Move xmm1 to r/m64. where m64 references the base pointer. +#[inline(always)] +fn movss_base32_offset32_freg32( + buf: &mut Vec<'_, u8>, + base: X86_64GeneralReg, + offset: i32, + src: X86_64FloatReg, +) { + let rex = add_rm_extension(base, REX_W); + let rex = add_reg_extension(src, rex); + let src_mod = (src as u8 % 8) << 3; + let base_mod = base as u8 % 8; + buf.reserve(10); + buf.push(0xF3); + if src as u8 > 7 || base as u8 > 7 { + buf.push(rex); + } + buf.extend([0x0F, 0x11, 0x80 | src_mod | base_mod]); + // Using RSP or R12 requires a secondary index byte. + if base == X86_64GeneralReg::RSP || base == X86_64GeneralReg::R12 { + buf.push(0x24); + } + buf.extend(offset.to_le_bytes()); +} + /// `MOVSD xmm1,r/m64` -> Move r/m64 to xmm1. where m64 references the base pointer. #[inline(always)] fn movsd_freg64_base64_offset32( @@ -3966,6 +3996,17 @@ mod tests { ); } + #[test] + fn test_movss_base64_offset32_freg64() { + disassembler_test!( + movss_base32_offset32_freg32, + |reg1, imm, reg2| format!("movss dword ptr [{} + 0x{:x}], {}", reg1, imm, reg2), + ALL_GENERAL_REGS, + [TEST_I32], + ALL_FLOAT_REGS + ); + } + #[test] fn test_mov_reg64_base64_offset32() { disassembler_test!(