Index: fpe/fpu_emulate.c =================================================================== RCS file: /cvsroot/src/sys/arch/m68k/fpe/fpu_emulate.c,v retrieving revision 1.49 diff -u -p -r1.49 fpu_emulate.c --- fpe/fpu_emulate.c 6 Jan 2025 07:34:24 -0000 1.49 +++ fpe/fpu_emulate.c 30 Oct 2026 20:27:58 -0000 @@ -148,6 +148,20 @@ fpu_emulate(struct frame *frame, struct DPRINTF(("%s: fault reading word1\n", __func__)); fpe_abort(frame, ksi, SIGSEGV, SEGV_ACCERR); } + + /* + * At this point, we know we're going to execute some sort of + * FP instruction. Set the FP frame state to mimic 68881 + * idle state so that other logic elsewhere can interact with + * the FP state in the PCB in natural way. + * + * If a program never executes an (emulated) FP instruction, then + * the version field will remain 0, and e.g. cpu_getmcontext() + * won't bother to save it. + */ + fpf->fpf_version = 0x1f; + fpf->fpf_fsize = 0x18; + insn.is_word1 = sval; /* all FPU instructions are at least 4-byte long */ insn.is_advance = 4; Index: m68k/sig_machdep.c =================================================================== RCS file: /cvsroot/src/sys/arch/m68k/m68k/sig_machdep.c,v retrieving revision 1.53 diff -u -p -r1.53 sig_machdep.c --- m68k/sig_machdep.c 30 Aug 2026 00:38:49 -0000 1.53 +++ m68k/sig_machdep.c 30 Oct 2026 20:27:58 -0000 @@ -254,31 +254,31 @@ cpu_getmcontext(struct lwp *l, mcontext_ frame->f_format = frame->f_vector = 0; } - if (fputype != FPU_NONE) { - /* Save FPU context. */ - struct pcb *pcb = lwp_getpcb(l); - struct fpframe *fpf = &pcb->pcb_fpregs; + struct pcb *pcb = lwp_getpcb(l); + struct fpframe *fpf = &pcb->pcb_fpregs; - /* - * If we're dealing with the current lwp, we need to - * save its FP state. Otherwise, its state is already - * store in its PCB. - */ - if (l == curlwp) - m68881_save(fpf); + /* + * Save FPU context. + * + * If we're dealing with the current lwp, we need to + * save its FP state. Otherwise, its state is already + * store in its PCB. + */ + if (fputype != FPU_NONE && l == curlwp) { + m68881_save(fpf); + } - mcp->__mc_pad.__mc_frame.__mcf_fpf_u1 = fpf->FPF_u1; + mcp->__mc_pad.__mc_frame.__mcf_fpf_u1 = fpf->FPF_u1; - /* If it's a null frame there's no need to save/convert. */ - if (!FPFRAME_IS_NULL(fpf)) { - mcp->__mc_pad.__mc_frame.__mcf_fpf_u2 = fpf->FPF_u2; - (void)memcpy(mcp->__fpregs.__fp_fpregs, - fpf->fpf_regs, sizeof(fpf->fpf_regs)); - mcp->__fpregs.__fp_pcr = fpf->fpf_fpcr; - mcp->__fpregs.__fp_psr = fpf->fpf_fpsr; - mcp->__fpregs.__fp_piaddr = fpf->fpf_fpiar; - *flags |= _UC_FPU; - } + /* If it's a null frame there's no need to save/convert. */ + if (!FPFRAME_IS_NULL(fpf)) { + mcp->__mc_pad.__mc_frame.__mcf_fpf_u2 = fpf->FPF_u2; + (void)memcpy(mcp->__fpregs.__fp_fpregs, + fpf->fpf_regs, sizeof(fpf->fpf_regs)); + mcp->__fpregs.__fp_pcr = fpf->fpf_fpcr; + mcp->__fpregs.__fp_psr = fpf->fpf_fpsr; + mcp->__fpregs.__fp_piaddr = fpf->fpf_fpiar; + *flags |= _UC_FPU; } } @@ -365,63 +365,62 @@ cpu_setmcontext(struct lwp *l, const mco frame->f_pc = gr[_REG_PC]; } - if (fputype != FPU_NONE) { - const __fpregset_t *fpr = &mcp->__fpregs; - struct pcb *pcb = lwp_getpcb(l); - struct fpframe *fpf = &pcb->pcb_fpregs; + const __fpregset_t *fpr = &mcp->__fpregs; + struct pcb *pcb = lwp_getpcb(l); + struct fpframe *fpf = &pcb->pcb_fpregs; - switch (flags & (_UC_FPU | _UC_M68K_UC_USER)) { - case _UC_FPU: - /* - * We're restoring FPU context saved by the above - * cpu_getmcontext(). We can do a full frestore if - * something other than an null frame was saved. - */ - fpf->FPF_u1 = mcp->__mc_pad.__mc_frame.__mcf_fpf_u1; - if (!FPFRAME_IS_NULL(fpf)) { - fpf->FPF_u2 = - mcp->__mc_pad.__mc_frame.__mcf_fpf_u2; - (void)memcpy(fpf->fpf_regs, - fpr->__fp_fpregs, sizeof(fpf->fpf_regs)); - fpf->fpf_fpcr = fpr->__fp_pcr; - fpf->fpf_fpsr = fpr->__fp_psr; - fpf->fpf_fpiar = fpr->__fp_piaddr; - } - break; - - case _UC_FPU | _UC_M68K_UC_USER: - /* - * We're restoring FPU context saved by the - * userland _getcontext_() function. Since there - * is no FPU frame to restore. We assume the FPU was - * "idle" when the frame was created, so use the - * cached idle frame. - */ - fpf->FPF_u1 = m68k_cached_fpu_idle_frame.FPF_u1; - fpf->FPF_u2 = m68k_cached_fpu_idle_frame.FPF_u2; - (void)memcpy(fpf->fpf_regs, fpr->__fp_fpregs, - sizeof(fpf->fpf_regs)); + switch (flags & (_UC_FPU | _UC_M68K_UC_USER)) { + case _UC_FPU: + /* + * We're restoring FPU context saved by the above + * cpu_getmcontext(). We can do a full frestore if + * something other than an null frame was saved. + */ + fpf->FPF_u1 = mcp->__mc_pad.__mc_frame.__mcf_fpf_u1; + if (!FPFRAME_IS_NULL(fpf)) { + fpf->FPF_u2 = + mcp->__mc_pad.__mc_frame.__mcf_fpf_u2; + (void)memcpy(fpf->fpf_regs, + fpr->__fp_fpregs, sizeof(fpf->fpf_regs)); fpf->fpf_fpcr = fpr->__fp_pcr; fpf->fpf_fpsr = fpr->__fp_psr; fpf->fpf_fpiar = fpr->__fp_piaddr; - break; - - default: - /* - * The saved context contains no FPU state. - * Restore a NULL frame. - */ - fpf->FPF_u1.FPF_null = 0; - break; } + break; + case _UC_FPU | _UC_M68K_UC_USER: /* - * We only need to restore FP state right now if we're - * dealing with curlwp. Otherwise, it'll be restored - * (from the PCB) when this lwp is given the CPU. + * We're restoring FPU context saved by the + * userland _getcontext_() function. Since there + * is no FPU frame to restore. We assume the FPU was + * "idle" when the frame was created, so use the + * cached idle frame. */ - if (l == curlwp) - m68881_restore(fpf); + fpf->FPF_u1 = m68k_cached_fpu_idle_frame.FPF_u1; + fpf->FPF_u2 = m68k_cached_fpu_idle_frame.FPF_u2; + (void)memcpy(fpf->fpf_regs, fpr->__fp_fpregs, + sizeof(fpf->fpf_regs)); + fpf->fpf_fpcr = fpr->__fp_pcr; + fpf->fpf_fpsr = fpr->__fp_psr; + fpf->fpf_fpiar = fpr->__fp_piaddr; + break; + + default: + /* + * The saved context contains no FPU state. + * Restore a NULL frame. + */ + fpf->FPF_u1.FPF_null = 0; + break; + } + + /* + * We only need to restore FP state right now if we're + * dealing with curlwp. Otherwise, it'll be restored + * (from the PCB) when this lwp is given the CPU. + */ + if (fputype != FPU_NONE && l == curlwp) { + m68881_restore(fpf); } if ((flags & _UC_TLSBASE) != 0)