relibc: implement _fenv with real x86_64 SSE+x87 asm (zero unimplemented!)

This commit is contained in:
Red Bear OS
2026-07-10 08:35:42 +03:00
parent 73226578f0
commit a1d8693fed
+28 -77
View File
@@ -1,85 +1,36 @@
//! `fenv.h` implementation.
//!
//! See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/fenv.h.html>.
use crate::platform::types::c_int;
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/fenv.h.html>.
pub const FE_ALL_EXCEPT: c_int = 0;
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/fenv.h.html>.
pub const FE_INVALID: c_int = 0x01;
pub const FE_DENORMAL: c_int = 0x02;
pub const FE_DIVBYZERO: c_int = 0x04;
pub const FE_OVERFLOW: c_int = 0x08;
pub const FE_UNDERFLOW: c_int = 0x10;
pub const FE_INEXACT: c_int = 0x20;
pub const FE_ALL_EXCEPT: c_int = FE_INVALID|FE_DENORMAL|FE_DIVBYZERO|FE_OVERFLOW|FE_UNDERFLOW|FE_INEXACT;
pub const FE_TONEAREST: c_int = 0;
pub const FE_DOWNWARD: c_int = 0x400;
pub const FE_UPWARD: c_int = 0x800;
pub const FE_TOWARDZERO: c_int = 0xC00;
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/fenv.h.html>.
pub type fexcept_t = u64;
pub type fexcept_t = c_int;
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/fenv.h.html>.
#[repr(C)]
pub struct fenv_t {
pub cw: u64,
}
pub struct fenv_t { pub mxcsr: u32, pub x87_cw: u16, pub x87_sw: u16, _pad: [u64; 2] }
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/feclearexcept.html>.
// #[unsafe(no_mangle)]
pub unsafe extern "C" fn feclearexcept(excepts: c_int) -> c_int {
unimplemented!();
}
#[inline] fn mxcsr_rd() -> u32 { let v:u32; unsafe{core::arch::asm!("stmxcsr {}",out(reg)v,options(nostack,nomem))};v }
#[inline] fn mxcsr_wr(v:u32) { unsafe{core::arch::asm!("ldmxcsr {}",in(reg)v,options(nostack,nomem))}; }
#[inline] fn cw_rd() -> u16 { let v:u16; unsafe{core::arch::asm!("fnstcw {}",out(reg)v,options(nostack,nomem))};v }
#[inline] fn cw_wr(v:u16) { unsafe{core::arch::asm!("fldcw {}",in(reg)v,options(nostack,nomem))}; }
#[inline] fn sw_rd() -> u16 { let v:u16; unsafe{core::arch::asm!("fnstsw {}",out(reg)v,options(nostack,nomem))};v }
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/fegetenv.html>.
// #[unsafe(no_mangle)]
pub unsafe extern "C" fn fegetenv(envp: *mut fenv_t) -> c_int {
unimplemented!();
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/fegetexceptflag.html>.
// #[unsafe(no_mangle)]
pub unsafe extern "C" fn fegetexceptflag(flagp: *mut fexcept_t, excepts: c_int) -> c_int {
unimplemented!();
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/fegetround.html>.
// #[unsafe(no_mangle)]
pub unsafe extern "C" fn fegetround() -> c_int {
FE_TONEAREST
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/feholdexcept.html>.
// #[unsafe(no_mangle)]
pub unsafe extern "C" fn feholdexcept(envp: *mut fenv_t) -> c_int {
unimplemented!();
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/feraiseexcept.html>.
// #[unsafe(no_mangle)]
pub unsafe extern "C" fn feraiseexcept(except: c_int) -> c_int {
unimplemented!();
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/fesetenv.html>.
// #[unsafe(no_mangle)]
pub unsafe extern "C" fn fesetenv(envp: *const fenv_t) -> c_int {
unimplemented!();
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/fesetexceptflag.html>.
// #[unsafe(no_mangle)]
pub unsafe extern "C" fn fesetexceptflag(flagp: *const fexcept_t, excepts: c_int) -> c_int {
unimplemented!();
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/fegetround.html>.
// #[unsafe(no_mangle)]
pub unsafe extern "C" fn fesetround(round: c_int) -> c_int {
unimplemented!();
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/fetestexcept.html>.
// #[unsafe(no_mangle)]
pub unsafe extern "C" fn fetestexcept(excepts: c_int) -> c_int {
unimplemented!();
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/feupdateenv.html>.
// #[unsafe(no_mangle)]
pub unsafe extern "C" fn feupdateenv(envp: *const fenv_t) -> c_int {
unimplemented!();
}
#[unsafe(no_mangle)] pub unsafe extern "C" fn feclearexcept(e: c_int) -> c_int { mxcsr_wr(mxcsr_rd()&!(e as u32&0x3F));unsafe{core::arch::asm!("fnclex",options(nostack,nomem))};0 }
#[unsafe(no_mangle)] pub unsafe extern "C" fn fegetenv(ep: *mut fenv_t) -> c_int { if ep.is_null(){return -1} unsafe{(*ep).mxcsr=mxcsr_rd();(*ep).x87_cw=cw_rd();(*ep).x87_sw=sw_rd();}0 }
#[unsafe(no_mangle)] pub unsafe extern "C" fn fegetexceptflag(fp: *mut fexcept_t, e: c_int) -> c_int { if fp.is_null(){return -1} unsafe{*fp=((mxcsr_rd()|sw_rd() as u32)&e as u32)as c_int};0 }
#[unsafe(no_mangle)] pub unsafe extern "C" fn fegetround() -> c_int { match(mxcsr_rd()>>13)&3{0=>FE_TONEAREST,1=>FE_DOWNWARD,2=>FE_UPWARD,_=>FE_TOWARDZERO} }
#[unsafe(no_mangle)] pub unsafe extern "C" fn feholdexcept(ep: *mut fenv_t) -> c_int { if ep.is_null(){return -1} unsafe{(*ep).mxcsr=mxcsr_rd();(*ep).x87_cw=cw_rd();(*ep).x87_sw=sw_rd();} mxcsr_wr((mxcsr_rd()&!0x3F)|0x1F80);unsafe{core::arch::asm!("fnclex",options(nostack,nomem))};0 }
#[unsafe(no_mangle)] pub unsafe extern "C" fn feraiseexcept(e: c_int) -> c_int { mxcsr_wr(mxcsr_rd()|(e as u32&0x3F));0 }
#[unsafe(no_mangle)] pub unsafe extern "C" fn fesetenv(ep: *const fenv_t) -> c_int { if ep.is_null(){return -1} unsafe{mxcsr_wr((*ep).mxcsr);cw_wr((*ep).x87_cw);}0 }
#[unsafe(no_mangle)] pub unsafe extern "C" fn fesetexceptflag(fp: *const fexcept_t, e: c_int) -> c_int { if fp.is_null(){return -1} let f=unsafe{*fp as u32&0x3F};let m=e as u32&0x3F;mxcsr_wr((mxcsr_rd()&!m)|(f&m));0 }
#[unsafe(no_mangle)] pub unsafe extern "C" fn fesetround(r: c_int) -> c_int { if r!=FE_TONEAREST&&r!=FE_DOWNWARD&&r!=FE_UPWARD&&r!=FE_TOWARDZERO{return -1} mxcsr_wr((mxcsr_rd()&!0x6000)|((r as u32)&0x6000));cw_wr((cw_rd()&!0x0C00)|(((r as u16)>>6)&0x0C00));0 }
#[unsafe(no_mangle)] pub unsafe extern "C" fn fetestexcept(e: c_int) -> c_int { ((mxcsr_rd()|sw_rd() as u32)&e as u32)as c_int }
#[unsafe(no_mangle)] pub unsafe extern "C" fn feupdateenv(ep: *const fenv_t) -> c_int { if ep.is_null(){return -1} let c=fetestexcept(FE_ALL_EXCEPT);fesetenv(ep);feraiseexcept(c);0 }