void _thread_machdep_save_float_state(struct _machdep_state *ms) { union savefpu *addr = &ms->fpreg; if (_thread_machdep_osfxsr()) { fwait(); fxsave(&addr->sv_xmm); fninit(); } else fnsave(&addr->sv_87); fwait(); }
void fputrap(struct trapframe *frame) { register struct lwp *l = curcpu()->ci_fpcurlwp; struct pcb *pcb = lwp_getpcb(l); struct savefpu *sfp = &pcb->pcb_savefpu; uint32_t mxcsr, statbits; uint16_t cw; ksiginfo_t ksi; KPREEMPT_DISABLE(l); x86_enable_intr(); /* * At this point, fpcurlwp should be curlwp. If it wasn't, the TS bit * should be set, and we should have gotten a DNA exception. */ KASSERT(l == curlwp); fxsave(sfp); pcb->pcb_savefpu_i387.fp_ex_tw = sfp->fp_fxsave.fx_ftw; pcb->pcb_savefpu_i387.fp_ex_sw = sfp->fp_fxsave.fx_fsw; if (frame->tf_trapno == T_XMM) { mxcsr = sfp->fp_fxsave.fx_mxcsr; statbits = mxcsr; mxcsr &= ~0x3f; x86_ldmxcsr(&mxcsr); } else { fninit(); fwait(); cw = sfp->fp_fxsave.fx_fcw; fldcw(&cw); fwait(); statbits = sfp->fp_fxsave.fx_fsw; } KPREEMPT_ENABLE(l); KSI_INIT_TRAP(&ksi); ksi.ksi_signo = SIGFPE; ksi.ksi_addr = (void *)frame->tf_rip; ksi.ksi_code = x86fpflags_to_ksiginfo(statbits); ksi.ksi_trap = statbits; (*l->l_proc->p_emul->e_trapsignal)(l, &ksi); }
/* The feraiseexcept function raises the supported floating-point exceptions represented by its argument. The order in which these floating-point exceptions are raised is unspecified, except as stated in F.7.6. Whether the feraiseexcept function additionally raises the inexact floating-point exception whenever it raises the overflow or underflow floating-point exception is implementation-defined. */ _WCRTLINK int feraiseexcept( int excepts ) /****************************************/ { fenv_t env; fenv_store( &env ); env.status_word |= excepts & FE_ALL_EXCEPT; fenv_load( &env ); fwait(); /* Make sure exception gets triggered now */ return( 0 ); }
void _thread_machdep_restore_float_state(struct _machdep_state *ms) { union savefpu *addr = &ms->fpreg; if (_thread_machdep_osfxsr()) { fxrstor(&addr->sv_xmm); fwait(); } else frstor(&addr->sv_87); }