Home | History | Annotate | Line # | Download | only in mips
      1 /* $NetBSD: mips_fputrap.c,v 1.13 2025/05/03 02:00:46 riastradh Exp $ */
      2 
      3 /*
      4  * Copyright (c) 2004
      5  *	Matthias Drochner. All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions, and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #ifdef _KERNEL_OPT
     30 #include "opt_cputype.h"
     31 #endif
     32 
     33 #include <sys/param.h>
     34 #include <sys/systm.h>
     35 #include <sys/proc.h>
     36 #include <sys/signal.h>
     37 #include <sys/siginfo.h>
     38 
     39 #include <mips/cpuregs.h>
     40 #include <mips/regnum.h>
     41 #include <mips/locore.h>
     42 
     43 #if defined(FPEMUL) || !defined(NOFPU)
     44 void mips_fpuexcept(struct lwp *, uint32_t);
     45 void mips_fpuillinst(struct lwp *, uint32_t);
     46 static int fpustat2sicode(uint32_t);
     47 
     48 void
     49 mips_fpuexcept(struct lwp *l, uint32_t fpustat)
     50 {
     51 	ksiginfo_t ksi;
     52 
     53 #ifdef FPEMUL_DEBUG
     54 	printf("%s(%#x,%#"PRIxREGISTER")\n",
     55 	   __func__, fpustat, l->l_md.md_utf->tf_regs[_R_PC]);
     56 #endif
     57 
     58 	KSI_INIT_TRAP(&ksi);
     59 	ksi.ksi_signo = SIGFPE;
     60 	ksi.ksi_code = fpustat2sicode(fpustat);
     61 	ksi.ksi_trap = fpustat;
     62 	(*l->l_proc->p_emul->e_trapsignal)(l, &ksi);
     63 }
     64 
     65 void
     66 mips_fpuillinst(struct lwp *l, uint32_t opcode)
     67 {
     68 	ksiginfo_t ksi;
     69 
     70 #ifdef FPEMUL_DEBUG
     71 	printf("%s(%#x,%#"PRIxREGISTER")\n",
     72 	   __func__, opcode, l->l_md.md_utf->tf_regs[_R_PC]);
     73 #endif
     74 
     75 	KSI_INIT_TRAP(&ksi);
     76 	ksi.ksi_signo = SIGILL;
     77 	ksi.ksi_code = ILL_ILLOPC;
     78 	ksi.ksi_trap = opcode;
     79 	ksi.ksi_addr = (void *)(uintptr_t)l->l_md.md_utf->tf_regs[_R_PC];
     80 	(*l->l_proc->p_emul->e_trapsignal)(l, &ksi);
     81 }
     82 
     83 static const struct {
     84 	unsigned int bit;
     85 	int code;
     86 } fpecodes[] = {
     87 	{ MIPS_FCSR_CAUSE_I, FPE_FLTRES },
     88 	{ MIPS_FCSR_CAUSE_U, FPE_FLTUND },
     89 	{ MIPS_FCSR_CAUSE_O, FPE_FLTOVF },
     90 	{ MIPS_FCSR_CAUSE_Z, FPE_FLTDIV },
     91 	{ MIPS_FCSR_CAUSE_V, FPE_FLTINV },
     92 	{ MIPS_FCSR_CAUSE_E, FPE_FLTINV }
     93 };
     94 
     95 static int
     96 fpustat2sicode(uint32_t fpustat)
     97 {
     98 	for (size_t i = 0; i < __arraycount(fpecodes); i++) {
     99 		if (fpustat & fpecodes[i].bit)
    100 			return fpecodes[i].code;
    101 	}
    102 
    103 	return FPE_FLTINV;
    104 }
    105 #endif /* FPEMUL || !NOFPU */
    106