^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) }