18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Linux/PA-RISC Project (http://www.parisc-linux.org/)
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Floating-point emulation code
68c2ecf20Sopenharmony_ci *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci/*
98c2ecf20Sopenharmony_ci * BEGIN_DESC
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci *  File:
128c2ecf20Sopenharmony_ci *	@(#)	pa/fp/decode_exc.c		$ Revision: $
138c2ecf20Sopenharmony_ci *
148c2ecf20Sopenharmony_ci *  Purpose:
158c2ecf20Sopenharmony_ci *	<<please update with a synopsis of the functionality provided by this file>>
168c2ecf20Sopenharmony_ci *
178c2ecf20Sopenharmony_ci *  External Interfaces:
188c2ecf20Sopenharmony_ci *	<<the following list was autogenerated, please review>>
198c2ecf20Sopenharmony_ci *	decode_fpu(Fpu_register, trap_counts)
208c2ecf20Sopenharmony_ci *
218c2ecf20Sopenharmony_ci *  Internal Interfaces:
228c2ecf20Sopenharmony_ci *	<<please update>>
238c2ecf20Sopenharmony_ci *
248c2ecf20Sopenharmony_ci *  Theory:
258c2ecf20Sopenharmony_ci *	<<please update with a overview of the operation of this file>>
268c2ecf20Sopenharmony_ci *
278c2ecf20Sopenharmony_ci * END_DESC
288c2ecf20Sopenharmony_ci*/
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci#include <linux/kernel.h>
318c2ecf20Sopenharmony_ci#include "float.h"
328c2ecf20Sopenharmony_ci#include "sgl_float.h"
338c2ecf20Sopenharmony_ci#include "dbl_float.h"
348c2ecf20Sopenharmony_ci#include "cnv_float.h"
358c2ecf20Sopenharmony_ci/* #include "types.h" */
368c2ecf20Sopenharmony_ci#include <asm/signal.h>
378c2ecf20Sopenharmony_ci#include <asm/siginfo.h>
388c2ecf20Sopenharmony_ci/* #include <machine/sys/mdep_private.h> */
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci#undef Fpustatus_register
418c2ecf20Sopenharmony_ci#define Fpustatus_register Fpu_register[0]
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci/* General definitions */
448c2ecf20Sopenharmony_ci#define DOESTRAP 1
458c2ecf20Sopenharmony_ci#define NOTRAP 0
468c2ecf20Sopenharmony_ci#define SIGNALCODE(signal, code) ((signal) << 24 | (code))
478c2ecf20Sopenharmony_ci#define copropbit	1<<31-2	/* bit position 2 */
488c2ecf20Sopenharmony_ci#define opclass		9	/* bits 21 & 22 */
498c2ecf20Sopenharmony_ci#define fmt		11	/* bits 19 & 20 */
508c2ecf20Sopenharmony_ci#define df		13	/* bits 17 & 18 */
518c2ecf20Sopenharmony_ci#define twobits		3	/* mask low-order 2 bits */
528c2ecf20Sopenharmony_ci#define fivebits	31	/* mask low-order 5 bits */
538c2ecf20Sopenharmony_ci#define MAX_EXCP_REG	7	/* number of excpeption registers to check */
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci/* Exception register definitions */
568c2ecf20Sopenharmony_ci#define Excp_type(index) Exceptiontype(Fpu_register[index])
578c2ecf20Sopenharmony_ci#define Excp_instr(index) Instructionfield(Fpu_register[index])
588c2ecf20Sopenharmony_ci#define Clear_excp_register(index) Allexception(Fpu_register[index]) = 0
598c2ecf20Sopenharmony_ci#define Excp_format() \
608c2ecf20Sopenharmony_ci    (current_ir >> ((current_ir>>opclass & twobits)==1 ? df : fmt) & twobits)
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci/* Miscellaneous definitions */
638c2ecf20Sopenharmony_ci#define Fpu_sgl(index) Fpu_register[index*2]
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci#define Fpu_dblp1(index) Fpu_register[index*2]
668c2ecf20Sopenharmony_ci#define Fpu_dblp2(index) Fpu_register[(index*2)+1]
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci#define Fpu_quadp1(index) Fpu_register[index*2]
698c2ecf20Sopenharmony_ci#define Fpu_quadp2(index) Fpu_register[(index*2)+1]
708c2ecf20Sopenharmony_ci#define Fpu_quadp3(index) Fpu_register[(index*2)+2]
718c2ecf20Sopenharmony_ci#define Fpu_quadp4(index) Fpu_register[(index*2)+3]
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci/* Single precision floating-point definitions */
748c2ecf20Sopenharmony_ci#ifndef Sgl_decrement
758c2ecf20Sopenharmony_ci# define Sgl_decrement(sgl_value) Sall(sgl_value)--
768c2ecf20Sopenharmony_ci#endif
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci/* Double precision floating-point definitions */
798c2ecf20Sopenharmony_ci#ifndef Dbl_decrement
808c2ecf20Sopenharmony_ci# define Dbl_decrement(dbl_valuep1,dbl_valuep2) \
818c2ecf20Sopenharmony_ci    if ((Dallp2(dbl_valuep2)--) == 0) Dallp1(dbl_valuep1)--
828c2ecf20Sopenharmony_ci#endif
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci#define update_trap_counts(Fpu_register, aflags, bflags, trap_counts) {	\
868c2ecf20Sopenharmony_ci	aflags=(Fpu_register[0])>>27;	/* assumes zero fill. 32 bit */	\
878c2ecf20Sopenharmony_ci	Fpu_register[0] |= bflags;					\
888c2ecf20Sopenharmony_ci}
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ciu_int
918c2ecf20Sopenharmony_cidecode_fpu(unsigned int Fpu_register[], unsigned int trap_counts[])
928c2ecf20Sopenharmony_ci{
938c2ecf20Sopenharmony_ci    unsigned int current_ir, excp;
948c2ecf20Sopenharmony_ci    int target, exception_index = 1;
958c2ecf20Sopenharmony_ci    boolean inexact;
968c2ecf20Sopenharmony_ci    unsigned int aflags;
978c2ecf20Sopenharmony_ci    unsigned int bflags;
988c2ecf20Sopenharmony_ci    unsigned int excptype;
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci    /* Keep stats on how many floating point exceptions (based on type)
1028c2ecf20Sopenharmony_ci     * that happen.  Want to keep this overhead low, but still provide
1038c2ecf20Sopenharmony_ci     * some information to the customer.  All exits from this routine
1048c2ecf20Sopenharmony_ci     * need to restore Fpu_register[0]
1058c2ecf20Sopenharmony_ci    */
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci    bflags=(Fpu_register[0] & 0xf8000000);
1088c2ecf20Sopenharmony_ci    Fpu_register[0] &= 0x07ffffff;
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci    /* exception_index is used to index the exception register queue.  It
1118c2ecf20Sopenharmony_ci     *   always points at the last register that contains a valid exception.  A
1128c2ecf20Sopenharmony_ci     *   zero value implies no exceptions (also the initialized value).  Setting
1138c2ecf20Sopenharmony_ci     *   the T-bit resets the exception_index to zero.
1148c2ecf20Sopenharmony_ci     */
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci    /*
1178c2ecf20Sopenharmony_ci     * Check for reserved-op exception.  A reserved-op exception does not
1188c2ecf20Sopenharmony_ci     * set any exception registers nor does it set the T-bit.  If the T-bit
1198c2ecf20Sopenharmony_ci     * is not set then a reserved-op exception occurred.
1208c2ecf20Sopenharmony_ci     *
1218c2ecf20Sopenharmony_ci     * At some point, we may want to report reserved op exceptions as
1228c2ecf20Sopenharmony_ci     * illegal instructions.
1238c2ecf20Sopenharmony_ci     */
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci    if (!Is_tbit_set()) {
1268c2ecf20Sopenharmony_ci	update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
1278c2ecf20Sopenharmony_ci	return SIGNALCODE(SIGILL, ILL_COPROC);
1288c2ecf20Sopenharmony_ci    }
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci    /*
1318c2ecf20Sopenharmony_ci     * Is a coprocessor op.
1328c2ecf20Sopenharmony_ci     *
1338c2ecf20Sopenharmony_ci     * Now we need to determine what type of exception occurred.
1348c2ecf20Sopenharmony_ci     */
1358c2ecf20Sopenharmony_ci    for (exception_index=1; exception_index<=MAX_EXCP_REG; exception_index++) {
1368c2ecf20Sopenharmony_ci	current_ir = Excp_instr(exception_index);
1378c2ecf20Sopenharmony_ci	  /*
1388c2ecf20Sopenharmony_ci	   * On PA89: there are 5 different unimplemented exception
1398c2ecf20Sopenharmony_ci	   * codes: 0x1, 0x9, 0xb, 0x3, and 0x23.  PA-RISC 2.0 adds
1408c2ecf20Sopenharmony_ci	   * another, 0x2b.  Only these have the low order bit set.
1418c2ecf20Sopenharmony_ci	   */
1428c2ecf20Sopenharmony_ci	excptype = Excp_type(exception_index);
1438c2ecf20Sopenharmony_ci	if (excptype & UNIMPLEMENTEDEXCEPTION) {
1448c2ecf20Sopenharmony_ci		/*
1458c2ecf20Sopenharmony_ci		 * Clear T-bit and exception register so that
1468c2ecf20Sopenharmony_ci		 * we can tell if a trap really occurs while
1478c2ecf20Sopenharmony_ci		 * emulating the instruction.
1488c2ecf20Sopenharmony_ci		 */
1498c2ecf20Sopenharmony_ci		Clear_tbit();
1508c2ecf20Sopenharmony_ci		Clear_excp_register(exception_index);
1518c2ecf20Sopenharmony_ci		/*
1528c2ecf20Sopenharmony_ci		 * Now emulate this instruction.  If a trap occurs,
1538c2ecf20Sopenharmony_ci		 * fpudispatch will return a non-zero number
1548c2ecf20Sopenharmony_ci		 */
1558c2ecf20Sopenharmony_ci		excp = fpudispatch(current_ir,excptype,0,Fpu_register);
1568c2ecf20Sopenharmony_ci		/* accumulate the status flags, don't lose them as in hpux */
1578c2ecf20Sopenharmony_ci		if (excp) {
1588c2ecf20Sopenharmony_ci			/*
1598c2ecf20Sopenharmony_ci			 * We now need to make sure that the T-bit and the
1608c2ecf20Sopenharmony_ci			 * exception register contain the correct values
1618c2ecf20Sopenharmony_ci			 * before continuing.
1628c2ecf20Sopenharmony_ci			 */
1638c2ecf20Sopenharmony_ci			/*
1648c2ecf20Sopenharmony_ci			 * Set t-bit since it might still be needed for a
1658c2ecf20Sopenharmony_ci			 * subsequent real trap (I don't understand fully -PB)
1668c2ecf20Sopenharmony_ci			 */
1678c2ecf20Sopenharmony_ci			Set_tbit();
1688c2ecf20Sopenharmony_ci			/* some of the following code uses
1698c2ecf20Sopenharmony_ci			 * Excp_type(exception_index) so fix that up */
1708c2ecf20Sopenharmony_ci			Set_exceptiontype_and_instr_field(excp,current_ir,
1718c2ecf20Sopenharmony_ci			 Fpu_register[exception_index]);
1728c2ecf20Sopenharmony_ci			if (excp == UNIMPLEMENTEDEXCEPTION) {
1738c2ecf20Sopenharmony_ci				/*
1748c2ecf20Sopenharmony_ci			 	 * it is really unimplemented, so restore the
1758c2ecf20Sopenharmony_ci			 	 * TIMEX extended unimplemented exception code
1768c2ecf20Sopenharmony_ci			 	 */
1778c2ecf20Sopenharmony_ci				excp = excptype;
1788c2ecf20Sopenharmony_ci				update_trap_counts(Fpu_register, aflags, bflags,
1798c2ecf20Sopenharmony_ci					   trap_counts);
1808c2ecf20Sopenharmony_ci				return SIGNALCODE(SIGILL, ILL_COPROC);
1818c2ecf20Sopenharmony_ci			}
1828c2ecf20Sopenharmony_ci			/* some of the following code uses excptype, so
1838c2ecf20Sopenharmony_ci			 * fix that up too */
1848c2ecf20Sopenharmony_ci			excptype = excp;
1858c2ecf20Sopenharmony_ci		}
1868c2ecf20Sopenharmony_ci		/* handle exceptions other than the real UNIMPLIMENTED the
1878c2ecf20Sopenharmony_ci		 * same way as if the hardware had caused them */
1888c2ecf20Sopenharmony_ci		if (excp == NOEXCEPTION)
1898c2ecf20Sopenharmony_ci			/* For now use 'break', should technically be 'continue' */
1908c2ecf20Sopenharmony_ci			break;
1918c2ecf20Sopenharmony_ci	}
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci	  /*
1948c2ecf20Sopenharmony_ci	   * In PA89, the underflow exception has been extended to encode
1958c2ecf20Sopenharmony_ci	   * additional information.  The exception looks like pp01x0,
1968c2ecf20Sopenharmony_ci	   * where x is 1 if inexact and pp represent the inexact bit (I)
1978c2ecf20Sopenharmony_ci	   * and the round away bit (RA)
1988c2ecf20Sopenharmony_ci	   */
1998c2ecf20Sopenharmony_ci	if (excptype & UNDERFLOWEXCEPTION) {
2008c2ecf20Sopenharmony_ci		/* check for underflow trap enabled */
2018c2ecf20Sopenharmony_ci		if (Is_underflowtrap_enabled()) {
2028c2ecf20Sopenharmony_ci			update_trap_counts(Fpu_register, aflags, bflags,
2038c2ecf20Sopenharmony_ci					   trap_counts);
2048c2ecf20Sopenharmony_ci			return SIGNALCODE(SIGFPE, FPE_FLTUND);
2058c2ecf20Sopenharmony_ci		} else {
2068c2ecf20Sopenharmony_ci		    /*
2078c2ecf20Sopenharmony_ci		     * Isn't a real trap; we need to
2088c2ecf20Sopenharmony_ci		     * return the default value.
2098c2ecf20Sopenharmony_ci		     */
2108c2ecf20Sopenharmony_ci		    target = current_ir & fivebits;
2118c2ecf20Sopenharmony_ci#ifndef lint
2128c2ecf20Sopenharmony_ci		    if (Ibit(Fpu_register[exception_index])) inexact = TRUE;
2138c2ecf20Sopenharmony_ci		    else inexact = FALSE;
2148c2ecf20Sopenharmony_ci#endif
2158c2ecf20Sopenharmony_ci		    switch (Excp_format()) {
2168c2ecf20Sopenharmony_ci		      case SGL:
2178c2ecf20Sopenharmony_ci		        /*
2188c2ecf20Sopenharmony_ci		         * If ra (round-away) is set, will
2198c2ecf20Sopenharmony_ci		         * want to undo the rounding done
2208c2ecf20Sopenharmony_ci		         * by the hardware.
2218c2ecf20Sopenharmony_ci		         */
2228c2ecf20Sopenharmony_ci		        if (Rabit(Fpu_register[exception_index]))
2238c2ecf20Sopenharmony_ci				Sgl_decrement(Fpu_sgl(target));
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci			/* now denormalize */
2268c2ecf20Sopenharmony_ci			sgl_denormalize(&Fpu_sgl(target),&inexact,Rounding_mode());
2278c2ecf20Sopenharmony_ci		    	break;
2288c2ecf20Sopenharmony_ci		      case DBL:
2298c2ecf20Sopenharmony_ci		    	/*
2308c2ecf20Sopenharmony_ci		    	 * If ra (round-away) is set, will
2318c2ecf20Sopenharmony_ci		    	 * want to undo the rounding done
2328c2ecf20Sopenharmony_ci		    	 * by the hardware.
2338c2ecf20Sopenharmony_ci		    	 */
2348c2ecf20Sopenharmony_ci		    	if (Rabit(Fpu_register[exception_index]))
2358c2ecf20Sopenharmony_ci				Dbl_decrement(Fpu_dblp1(target),Fpu_dblp2(target));
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci			/* now denormalize */
2388c2ecf20Sopenharmony_ci			dbl_denormalize(&Fpu_dblp1(target),&Fpu_dblp2(target),
2398c2ecf20Sopenharmony_ci			  &inexact,Rounding_mode());
2408c2ecf20Sopenharmony_ci		    	break;
2418c2ecf20Sopenharmony_ci		    }
2428c2ecf20Sopenharmony_ci		    if (inexact) Set_underflowflag();
2438c2ecf20Sopenharmony_ci		    /*
2448c2ecf20Sopenharmony_ci		     * Underflow can generate an inexact
2458c2ecf20Sopenharmony_ci		     * exception.  If inexact trap is enabled,
2468c2ecf20Sopenharmony_ci		     * want to do an inexact trap, otherwise
2478c2ecf20Sopenharmony_ci		     * set inexact flag.
2488c2ecf20Sopenharmony_ci		     */
2498c2ecf20Sopenharmony_ci		    if (inexact && Is_inexacttrap_enabled()) {
2508c2ecf20Sopenharmony_ci		    	/*
2518c2ecf20Sopenharmony_ci		    	 * Set exception field of exception register
2528c2ecf20Sopenharmony_ci		    	 * to inexact, parm field to zero.
2538c2ecf20Sopenharmony_ci			 * Underflow bit should be cleared.
2548c2ecf20Sopenharmony_ci		    	 */
2558c2ecf20Sopenharmony_ci		    	Set_exceptiontype(Fpu_register[exception_index],
2568c2ecf20Sopenharmony_ci			 INEXACTEXCEPTION);
2578c2ecf20Sopenharmony_ci			Set_parmfield(Fpu_register[exception_index],0);
2588c2ecf20Sopenharmony_ci			update_trap_counts(Fpu_register, aflags, bflags,
2598c2ecf20Sopenharmony_ci					   trap_counts);
2608c2ecf20Sopenharmony_ci			return SIGNALCODE(SIGFPE, FPE_FLTRES);
2618c2ecf20Sopenharmony_ci		    }
2628c2ecf20Sopenharmony_ci		    else {
2638c2ecf20Sopenharmony_ci		    	/*
2648c2ecf20Sopenharmony_ci		    	 * Exception register needs to be cleared.
2658c2ecf20Sopenharmony_ci			 * Inexact flag needs to be set if inexact.
2668c2ecf20Sopenharmony_ci		    	 */
2678c2ecf20Sopenharmony_ci		    	Clear_excp_register(exception_index);
2688c2ecf20Sopenharmony_ci		    	if (inexact) Set_inexactflag();
2698c2ecf20Sopenharmony_ci		    }
2708c2ecf20Sopenharmony_ci		}
2718c2ecf20Sopenharmony_ci		continue;
2728c2ecf20Sopenharmony_ci	}
2738c2ecf20Sopenharmony_ci	switch(Excp_type(exception_index)) {
2748c2ecf20Sopenharmony_ci	  case OVERFLOWEXCEPTION:
2758c2ecf20Sopenharmony_ci	  case OVERFLOWEXCEPTION | INEXACTEXCEPTION:
2768c2ecf20Sopenharmony_ci		/* check for overflow trap enabled */
2778c2ecf20Sopenharmony_ci			update_trap_counts(Fpu_register, aflags, bflags,
2788c2ecf20Sopenharmony_ci					   trap_counts);
2798c2ecf20Sopenharmony_ci		if (Is_overflowtrap_enabled()) {
2808c2ecf20Sopenharmony_ci			update_trap_counts(Fpu_register, aflags, bflags,
2818c2ecf20Sopenharmony_ci					   trap_counts);
2828c2ecf20Sopenharmony_ci			return SIGNALCODE(SIGFPE, FPE_FLTOVF);
2838c2ecf20Sopenharmony_ci		} else {
2848c2ecf20Sopenharmony_ci			/*
2858c2ecf20Sopenharmony_ci			 * Isn't a real trap; we need to
2868c2ecf20Sopenharmony_ci			 * return the default value.
2878c2ecf20Sopenharmony_ci			 */
2888c2ecf20Sopenharmony_ci			target = current_ir & fivebits;
2898c2ecf20Sopenharmony_ci			switch (Excp_format()) {
2908c2ecf20Sopenharmony_ci			  case SGL:
2918c2ecf20Sopenharmony_ci				Sgl_setoverflow(Fpu_sgl(target));
2928c2ecf20Sopenharmony_ci				break;
2938c2ecf20Sopenharmony_ci			  case DBL:
2948c2ecf20Sopenharmony_ci				Dbl_setoverflow(Fpu_dblp1(target),Fpu_dblp2(target));
2958c2ecf20Sopenharmony_ci				break;
2968c2ecf20Sopenharmony_ci			}
2978c2ecf20Sopenharmony_ci			Set_overflowflag();
2988c2ecf20Sopenharmony_ci			/*
2998c2ecf20Sopenharmony_ci			 * Overflow always generates an inexact
3008c2ecf20Sopenharmony_ci			 * exception.  If inexact trap is enabled,
3018c2ecf20Sopenharmony_ci			 * want to do an inexact trap, otherwise
3028c2ecf20Sopenharmony_ci			 * set inexact flag.
3038c2ecf20Sopenharmony_ci			 */
3048c2ecf20Sopenharmony_ci			if (Is_inexacttrap_enabled()) {
3058c2ecf20Sopenharmony_ci				/*
3068c2ecf20Sopenharmony_ci				 * Set exception field of exception
3078c2ecf20Sopenharmony_ci				 * register to inexact.  Overflow
3088c2ecf20Sopenharmony_ci				 * bit should be cleared.
3098c2ecf20Sopenharmony_ci				 */
3108c2ecf20Sopenharmony_ci				Set_exceptiontype(Fpu_register[exception_index],
3118c2ecf20Sopenharmony_ci				 INEXACTEXCEPTION);
3128c2ecf20Sopenharmony_ci				update_trap_counts(Fpu_register, aflags, bflags,
3138c2ecf20Sopenharmony_ci					   trap_counts);
3148c2ecf20Sopenharmony_ci				return SIGNALCODE(SIGFPE, FPE_FLTRES);
3158c2ecf20Sopenharmony_ci			}
3168c2ecf20Sopenharmony_ci			else {
3178c2ecf20Sopenharmony_ci				/*
3188c2ecf20Sopenharmony_ci				 * Exception register needs to be cleared.
3198c2ecf20Sopenharmony_ci				 * Inexact flag needs to be set.
3208c2ecf20Sopenharmony_ci				 */
3218c2ecf20Sopenharmony_ci				Clear_excp_register(exception_index);
3228c2ecf20Sopenharmony_ci				Set_inexactflag();
3238c2ecf20Sopenharmony_ci			}
3248c2ecf20Sopenharmony_ci		}
3258c2ecf20Sopenharmony_ci		break;
3268c2ecf20Sopenharmony_ci	  case INVALIDEXCEPTION:
3278c2ecf20Sopenharmony_ci	  case OPC_2E_INVALIDEXCEPTION:
3288c2ecf20Sopenharmony_ci		update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
3298c2ecf20Sopenharmony_ci		return SIGNALCODE(SIGFPE, FPE_FLTINV);
3308c2ecf20Sopenharmony_ci	  case DIVISIONBYZEROEXCEPTION:
3318c2ecf20Sopenharmony_ci		update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
3328c2ecf20Sopenharmony_ci		Clear_excp_register(exception_index);
3338c2ecf20Sopenharmony_ci	  	return SIGNALCODE(SIGFPE, FPE_FLTDIV);
3348c2ecf20Sopenharmony_ci	  case INEXACTEXCEPTION:
3358c2ecf20Sopenharmony_ci		update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
3368c2ecf20Sopenharmony_ci		return SIGNALCODE(SIGFPE, FPE_FLTRES);
3378c2ecf20Sopenharmony_ci	  default:
3388c2ecf20Sopenharmony_ci		update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
3398c2ecf20Sopenharmony_ci		printk("%s(%d) Unknown FPU exception 0x%x\n", __FILE__,
3408c2ecf20Sopenharmony_ci			__LINE__, Excp_type(exception_index));
3418c2ecf20Sopenharmony_ci		return SIGNALCODE(SIGILL, ILL_COPROC);
3428c2ecf20Sopenharmony_ci	  case NOEXCEPTION:	/* no exception */
3438c2ecf20Sopenharmony_ci		/*
3448c2ecf20Sopenharmony_ci		 * Clear exception register in case
3458c2ecf20Sopenharmony_ci		 * other fields are non-zero.
3468c2ecf20Sopenharmony_ci		 */
3478c2ecf20Sopenharmony_ci		Clear_excp_register(exception_index);
3488c2ecf20Sopenharmony_ci		break;
3498c2ecf20Sopenharmony_ci	}
3508c2ecf20Sopenharmony_ci    }
3518c2ecf20Sopenharmony_ci    /*
3528c2ecf20Sopenharmony_ci     * No real exceptions occurred.
3538c2ecf20Sopenharmony_ci     */
3548c2ecf20Sopenharmony_ci    Clear_tbit();
3558c2ecf20Sopenharmony_ci    update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
3568c2ecf20Sopenharmony_ci    return(NOTRAP);
3578c2ecf20Sopenharmony_ci}
358