#[cfg(feature = "fp-simd")]
use core::{arch::naked_asm, mem::offset_of};
#[repr(C)]
#[derive(Debug, Default, Clone, Copy)]
pub struct FpuState {
pub fp: [u64; 32],
pub fp_high: [u64; 32],
pub fp_lasx_hi0: [u64; 32],
pub fp_lasx_hi1: [u64; 32],
pub fcc: [u8; 8],
pub fcsr: u32,
}
#[cfg(feature = "fp-simd")]
impl FpuState {
#[inline]
pub fn save(&mut self) {
unsafe { save_fp_registers(self) }
}
#[inline]
pub fn restore(&self) {
unsafe { restore_fp_registers(self) }
}
}
#[cfg(feature = "fp-simd")]
#[unsafe(naked)]
pub(super) unsafe extern "C" fn save_fp_registers(fpu: &mut FpuState) {
naked_asm!(
include_fp_asm_macros!(),
"
SAVE_FP $a0
addi.d $t8, $a0, {fp_high_offset}
SAVE_FP_HIGH $t8
csrrd $t0, 0x2
andi $t0, $t0, 0x4
beqz $t0, 1f
addi.d $t8, $a0, {fp_lasx_hi0_offset}
SAVE_FP_LASX_HI0 $t8
addi.d $t8, $a0, {fp_lasx_hi1_offset}
SAVE_FP_LASX_HI1 $t8
1:
addi.d $t8, $a0, {fcc_offset}
SAVE_FCC $t8
addi.d $t8, $a0, {fcsr_offset}
SAVE_FCSR $t8
ret",
fp_high_offset = const offset_of!(FpuState, fp_high),
fp_lasx_hi0_offset = const offset_of!(FpuState, fp_lasx_hi0),
fp_lasx_hi1_offset = const offset_of!(FpuState, fp_lasx_hi1),
fcc_offset = const offset_of!(FpuState, fcc),
fcsr_offset = const offset_of!(FpuState, fcsr),
)
}
#[cfg(feature = "fp-simd")]
#[unsafe(naked)]
pub(super) unsafe extern "C" fn restore_fp_registers(fpu: &FpuState) {
naked_asm!(
include_fp_asm_macros!(),
"
RESTORE_FP $a0
addi.d $t8, $a0, {fp_high_offset}
RESTORE_FP_HIGH $t8
csrrd $t0, 0x2
andi $t0, $t0, 0x4
beqz $t0, 1f
addi.d $t8, $a0, {fp_lasx_hi0_offset}
RESTORE_FP_LASX_HI0 $t8
addi.d $t8, $a0, {fp_lasx_hi1_offset}
RESTORE_FP_LASX_HI1 $t8
1:
addi.d $t8, $a0, {fcc_offset}
RESTORE_FCC $t8
addi.d $t8, $a0, {fcsr_offset}
RESTORE_FCSR $t8
ret",
fp_high_offset = const offset_of!(FpuState, fp_high),
fp_lasx_hi0_offset = const offset_of!(FpuState, fp_lasx_hi0),
fp_lasx_hi1_offset = const offset_of!(FpuState, fp_lasx_hi1),
fcc_offset = const offset_of!(FpuState, fcc),
fcsr_offset = const offset_of!(FpuState, fcsr),
)
}