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