Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Linux/PA-RISC Project (http://www.parisc-linux.org/)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Floating-point emulation code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * BEGIN_DESC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  *  File:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  *	@(#)	pa/fp/decode_exc.c		$ Revision: $
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  *  Purpose:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  *	<<please update with a synopsis of the functionality provided by this file>>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  *  External Interfaces:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  *	<<the following list was autogenerated, please review>>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  *	decode_fpu(Fpu_register, trap_counts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  *  Internal Interfaces:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  *	<<please update>>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  *  Theory:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  *	<<please update with a overview of the operation of this file>>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  * END_DESC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #include "float.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #include "sgl_float.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #include "dbl_float.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #include "cnv_float.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) /* #include "types.h" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) #include <asm/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #include <asm/siginfo.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) /* #include <machine/sys/mdep_private.h> */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) #undef Fpustatus_register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) #define Fpustatus_register Fpu_register[0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) /* General definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) #define DOESTRAP 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) #define NOTRAP 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) #define SIGNALCODE(signal, code) ((signal) << 24 | (code))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) #define copropbit	1<<31-2	/* bit position 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) #define opclass		9	/* bits 21 & 22 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) #define fmt		11	/* bits 19 & 20 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) #define df		13	/* bits 17 & 18 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) #define twobits		3	/* mask low-order 2 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) #define fivebits	31	/* mask low-order 5 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) #define MAX_EXCP_REG	7	/* number of excpeption registers to check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) /* Exception register definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) #define Excp_type(index) Exceptiontype(Fpu_register[index])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) #define Excp_instr(index) Instructionfield(Fpu_register[index])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) #define Clear_excp_register(index) Allexception(Fpu_register[index]) = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) #define Excp_format() \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60)     (current_ir >> ((current_ir>>opclass & twobits)==1 ? df : fmt) & twobits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) /* Miscellaneous definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) #define Fpu_sgl(index) Fpu_register[index*2]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) #define Fpu_dblp1(index) Fpu_register[index*2]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) #define Fpu_dblp2(index) Fpu_register[(index*2)+1]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) #define Fpu_quadp1(index) Fpu_register[index*2]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) #define Fpu_quadp2(index) Fpu_register[(index*2)+1]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) #define Fpu_quadp3(index) Fpu_register[(index*2)+2]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) #define Fpu_quadp4(index) Fpu_register[(index*2)+3]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) /* Single precision floating-point definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) #ifndef Sgl_decrement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) # define Sgl_decrement(sgl_value) Sall(sgl_value)--
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) /* Double precision floating-point definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) #ifndef Dbl_decrement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) # define Dbl_decrement(dbl_valuep1,dbl_valuep2) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81)     if ((Dallp2(dbl_valuep2)--) == 0) Dallp1(dbl_valuep1)-- 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) #define update_trap_counts(Fpu_register, aflags, bflags, trap_counts) {	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	aflags=(Fpu_register[0])>>27;	/* assumes zero fill. 32 bit */	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	Fpu_register[0] |= bflags;					\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) u_int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) decode_fpu(unsigned int Fpu_register[], unsigned int trap_counts[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93)     unsigned int current_ir, excp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94)     int target, exception_index = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95)     boolean inexact;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96)     unsigned int aflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97)     unsigned int bflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98)     unsigned int excptype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)     /* Keep stats on how many floating point exceptions (based on type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)      * that happen.  Want to keep this overhead low, but still provide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)      * some information to the customer.  All exits from this routine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)      * need to restore Fpu_register[0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)     */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)     bflags=(Fpu_register[0] & 0xf8000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)     Fpu_register[0] &= 0x07ffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)     /* exception_index is used to index the exception register queue.  It
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)      *   always points at the last register that contains a valid exception.  A
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)      *   zero value implies no exceptions (also the initialized value).  Setting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)      *   the T-bit resets the exception_index to zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)     /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)      * Check for reserved-op exception.  A reserved-op exception does not 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)      * set any exception registers nor does it set the T-bit.  If the T-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)      * is not set then a reserved-op exception occurred.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)      *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)      * At some point, we may want to report reserved op exceptions as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)      * illegal instructions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)     if (!Is_tbit_set()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	return SIGNALCODE(SIGILL, ILL_COPROC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)     /* 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)      * Is a coprocessor op. 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)      *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)      * Now we need to determine what type of exception occurred.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)     for (exception_index=1; exception_index<=MAX_EXCP_REG; exception_index++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	current_ir = Excp_instr(exception_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	  /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	   * On PA89: there are 5 different unimplemented exception
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	   * codes: 0x1, 0x9, 0xb, 0x3, and 0x23.  PA-RISC 2.0 adds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	   * another, 0x2b.  Only these have the low order bit set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	   */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	excptype = Excp_type(exception_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	if (excptype & UNIMPLEMENTEDEXCEPTION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		 * Clear T-bit and exception register so that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		 * we can tell if a trap really occurs while 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		 * emulating the instruction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		Clear_tbit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		Clear_excp_register(exception_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 		 * Now emulate this instruction.  If a trap occurs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		 * fpudispatch will return a non-zero number 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		excp = fpudispatch(current_ir,excptype,0,Fpu_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		/* accumulate the status flags, don't lose them as in hpux */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		if (excp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 			 * We now need to make sure that the T-bit and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 			 * exception register contain the correct values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 			 * before continuing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 			 * Set t-bit since it might still be needed for a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 			 * subsequent real trap (I don't understand fully -PB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 			Set_tbit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 			/* some of the following code uses
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 			 * Excp_type(exception_index) so fix that up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 			Set_exceptiontype_and_instr_field(excp,current_ir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 			 Fpu_register[exception_index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 			if (excp == UNIMPLEMENTEDEXCEPTION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 				/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 			 	 * it is really unimplemented, so restore the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 			 	 * TIMEX extended unimplemented exception code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 			 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 				excp = excptype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 				update_trap_counts(Fpu_register, aflags, bflags, 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 					   trap_counts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 				return SIGNALCODE(SIGILL, ILL_COPROC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 			/* some of the following code uses excptype, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 			 * fix that up too */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 			excptype = excp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		/* handle exceptions other than the real UNIMPLIMENTED the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 		 * same way as if the hardware had caused them */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 		if (excp == NOEXCEPTION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 			/* For now use 'break', should technically be 'continue' */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	  /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	   * In PA89, the underflow exception has been extended to encode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	   * additional information.  The exception looks like pp01x0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	   * where x is 1 if inexact and pp represent the inexact bit (I)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	   * and the round away bit (RA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	   */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	if (excptype & UNDERFLOWEXCEPTION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 		/* check for underflow trap enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		if (Is_underflowtrap_enabled()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 			update_trap_counts(Fpu_register, aflags, bflags, 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 					   trap_counts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 			return SIGNALCODE(SIGFPE, FPE_FLTUND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 		    /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 		     * Isn't a real trap; we need to 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 		     * return the default value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 		     */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 		    target = current_ir & fivebits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) #ifndef lint
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 		    if (Ibit(Fpu_register[exception_index])) inexact = TRUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		    else inexact = FALSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 		    switch (Excp_format()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 		      case SGL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 		        /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 		         * If ra (round-away) is set, will 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 		         * want to undo the rounding done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 		         * by the hardware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 		         */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 		        if (Rabit(Fpu_register[exception_index])) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 				Sgl_decrement(Fpu_sgl(target));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 			/* now denormalize */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 			sgl_denormalize(&Fpu_sgl(target),&inexact,Rounding_mode());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		    	break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		      case DBL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		    	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		    	 * If ra (round-away) is set, will 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 		    	 * want to undo the rounding done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		    	 * by the hardware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		    	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 		    	if (Rabit(Fpu_register[exception_index])) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 				Dbl_decrement(Fpu_dblp1(target),Fpu_dblp2(target));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 			/* now denormalize */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 			dbl_denormalize(&Fpu_dblp1(target),&Fpu_dblp2(target),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 			  &inexact,Rounding_mode());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		    	break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 		    if (inexact) Set_underflowflag();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 		    /* 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 		     * Underflow can generate an inexact
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 		     * exception.  If inexact trap is enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 		     * want to do an inexact trap, otherwise 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 		     * set inexact flag.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 		     */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 		    if (inexact && Is_inexacttrap_enabled()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 		    	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 		    	 * Set exception field of exception register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 		    	 * to inexact, parm field to zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 			 * Underflow bit should be cleared.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 		    	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 		    	Set_exceptiontype(Fpu_register[exception_index],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 			 INEXACTEXCEPTION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 			Set_parmfield(Fpu_register[exception_index],0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 			update_trap_counts(Fpu_register, aflags, bflags, 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 					   trap_counts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 			return SIGNALCODE(SIGFPE, FPE_FLTRES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 		    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 		    else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 		    	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 		    	 * Exception register needs to be cleared.  
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 			 * Inexact flag needs to be set if inexact.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		    	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 		    	Clear_excp_register(exception_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 		    	if (inexact) Set_inexactflag();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 		    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 		continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	switch(Excp_type(exception_index)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	  case OVERFLOWEXCEPTION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	  case OVERFLOWEXCEPTION | INEXACTEXCEPTION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 		/* check for overflow trap enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 			update_trap_counts(Fpu_register, aflags, bflags, 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 					   trap_counts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 		if (Is_overflowtrap_enabled()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 			update_trap_counts(Fpu_register, aflags, bflags, 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 					   trap_counts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 			return SIGNALCODE(SIGFPE, FPE_FLTOVF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 			 * Isn't a real trap; we need to 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 			 * return the default value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 			target = current_ir & fivebits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 			switch (Excp_format()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 			  case SGL: 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 				Sgl_setoverflow(Fpu_sgl(target));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 			  case DBL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 				Dbl_setoverflow(Fpu_dblp1(target),Fpu_dblp2(target));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 			Set_overflowflag();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 			/* 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 			 * Overflow always generates an inexact
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 			 * exception.  If inexact trap is enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 			 * want to do an inexact trap, otherwise 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 			 * set inexact flag.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 			if (Is_inexacttrap_enabled()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 				/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 				 * Set exception field of exception
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 				 * register to inexact.  Overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 				 * bit should be cleared.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 				 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 				Set_exceptiontype(Fpu_register[exception_index],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 				 INEXACTEXCEPTION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 				update_trap_counts(Fpu_register, aflags, bflags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 					   trap_counts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 				return SIGNALCODE(SIGFPE, FPE_FLTRES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 			else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 				/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 				 * Exception register needs to be cleared.  
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 				 * Inexact flag needs to be set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 				 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 				Clear_excp_register(exception_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 				Set_inexactflag();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	  case INVALIDEXCEPTION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	  case OPC_2E_INVALIDEXCEPTION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 		update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 		return SIGNALCODE(SIGFPE, FPE_FLTINV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	  case DIVISIONBYZEROEXCEPTION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 		update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 		Clear_excp_register(exception_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	  	return SIGNALCODE(SIGFPE, FPE_FLTDIV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	  case INEXACTEXCEPTION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 		update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 		return SIGNALCODE(SIGFPE, FPE_FLTRES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	  default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 		update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 		printk("%s(%d) Unknown FPU exception 0x%x\n", __FILE__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 			__LINE__, Excp_type(exception_index));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 		return SIGNALCODE(SIGILL, ILL_COPROC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	  case NOEXCEPTION:	/* no exception */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 		 * Clear exception register in case 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 		 * other fields are non-zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 		Clear_excp_register(exception_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)     /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)      * No real exceptions occurred.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)     Clear_tbit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)     update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)     return(NOTRAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }