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
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*---------------------------------------------------------------------------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  |  errors.c                                                                 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  |                                                                           |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  |  The error handling functions for wm-FPU-emu                              |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  |                                                                           |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  | Copyright (C) 1992,1993,1994,1996                                         |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  |                  E-mail   billm@jacobi.maths.monash.edu.au                |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  |                                                                           |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  |                                                                           |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  +---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) /*---------------------------------------------------------------------------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  | Note:                                                                     |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  |    The file contains code which accesses user memory.                     |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  |    Emulator static data may change when user memory is accessed, due to   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  |    other processes using the emulator while swapping is in progress.      |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  +---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <linux/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #include "fpu_emu.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #include "fpu_system.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #include "exception.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #include "status_w.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #include "control_w.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #include "reg_constant.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #include "version.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) /* */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #undef PRINT_MESSAGES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) /* */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) void Un_impl(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	u_char byte1, FPU_modrm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	unsigned long address = FPU_ORIG_EIP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	RE_ENTRANT_CHECK_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	/* No need to check access_ok(), we have previously fetched these bytes. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	printk("Unimplemented FPU Opcode at eip=%p : ", (void __user *)address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	if (FPU_CS == __USER_CS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 		while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 			FPU_get_user(byte1, (u_char __user *) address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 			if ((byte1 & 0xf8) == 0xd8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 			printk("[%02x]", byte1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 			address++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 		printk("%02x ", byte1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 		FPU_get_user(FPU_modrm, 1 + (u_char __user *) address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 		if (FPU_modrm >= 0300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 			printk("%02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 			       FPU_modrm & 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 			printk("/%d\n", (FPU_modrm >> 3) & 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 		printk("cs selector = %04x\n", FPU_CS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	RE_ENTRANT_CHECK_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	EXCEPTION(EX_Invalid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) #endif /*  0  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)    Called for opcodes which are illegal and which are known to result in a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75)    SIGILL with a real 80486.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76)    */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) void FPU_illegal(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	math_abort(FPU_info, SIGILL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) void FPU_printall(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	static const char *tag_desc[] = { "Valid", "Zero", "ERROR", "Empty",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 		"DeNorm", "Inf", "NaN"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	u_char byte1, FPU_modrm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	unsigned long address = FPU_ORIG_EIP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	RE_ENTRANT_CHECK_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	/* No need to check access_ok(), we have previously fetched these bytes. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	printk("At %p:", (void *)address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	if (FPU_CS == __USER_CS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) #define MAX_PRINTED_BYTES 20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		for (i = 0; i < MAX_PRINTED_BYTES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 			FPU_get_user(byte1, (u_char __user *) address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 			if ((byte1 & 0xf8) == 0xd8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 				printk(" %02x", byte1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 			printk(" [%02x]", byte1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 			address++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 		if (i == MAX_PRINTED_BYTES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 			printk(" [more..]\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 			FPU_get_user(FPU_modrm, 1 + (u_char __user *) address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 			if (FPU_modrm >= 0300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 				printk(" %02x (%02x+%d)\n", FPU_modrm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 				       FPU_modrm & 0xf8, FPU_modrm & 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 				printk(" /%d, mod=%d rm=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 				       (FPU_modrm >> 3) & 7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 				       (FPU_modrm >> 6) & 3, FPU_modrm & 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 		printk("%04x\n", FPU_CS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	partial_status = status_word();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #ifdef DEBUGGING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	if (partial_status & SW_Backward)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 		printk("SW: backward compatibility\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	if (partial_status & SW_C3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		printk("SW: condition bit 3\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	if (partial_status & SW_C2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 		printk("SW: condition bit 2\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	if (partial_status & SW_C1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 		printk("SW: condition bit 1\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	if (partial_status & SW_C0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 		printk("SW: condition bit 0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	if (partial_status & SW_Summary)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		printk("SW: exception summary\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	if (partial_status & SW_Stack_Fault)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 		printk("SW: stack fault\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	if (partial_status & SW_Precision)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		printk("SW: loss of precision\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	if (partial_status & SW_Underflow)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 		printk("SW: underflow\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	if (partial_status & SW_Overflow)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		printk("SW: overflow\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	if (partial_status & SW_Zero_Div)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		printk("SW: divide by zero\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	if (partial_status & SW_Denorm_Op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		printk("SW: denormalized operand\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	if (partial_status & SW_Invalid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		printk("SW: invalid operation\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #endif /* DEBUGGING */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	printk(" SW: b=%d st=%d es=%d sf=%d cc=%d%d%d%d ef=%d%d%d%d%d%d\n", partial_status & 0x8000 ? 1 : 0,	/* busy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	       (partial_status & 0x3800) >> 11,	/* stack top pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	       partial_status & 0x80 ? 1 : 0,	/* Error summary status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	       partial_status & 0x40 ? 1 : 0,	/* Stack flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	       partial_status & SW_C3 ? 1 : 0, partial_status & SW_C2 ? 1 : 0,	/* cc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	       partial_status & SW_C1 ? 1 : 0, partial_status & SW_C0 ? 1 : 0,	/* cc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	       partial_status & SW_Precision ? 1 : 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	       partial_status & SW_Underflow ? 1 : 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	       partial_status & SW_Overflow ? 1 : 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	       partial_status & SW_Zero_Div ? 1 : 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	       partial_status & SW_Denorm_Op ? 1 : 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	       partial_status & SW_Invalid ? 1 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	printk(" CW: ic=%d rc=%d%d pc=%d%d iem=%d     ef=%d%d%d%d%d%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	       control_word & 0x1000 ? 1 : 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	       (control_word & 0x800) >> 11, (control_word & 0x400) >> 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	       (control_word & 0x200) >> 9, (control_word & 0x100) >> 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	       control_word & 0x80 ? 1 : 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	       control_word & SW_Precision ? 1 : 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	       control_word & SW_Underflow ? 1 : 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	       control_word & SW_Overflow ? 1 : 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	       control_word & SW_Zero_Div ? 1 : 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	       control_word & SW_Denorm_Op ? 1 : 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	       control_word & SW_Invalid ? 1 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	for (i = 0; i < 8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 		FPU_REG *r = &st(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 		u_char tagi = FPU_gettagi(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 		switch (tagi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 		case TAG_Empty:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		case TAG_Zero:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		case TAG_Special:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 			/* Update tagi for the printk below */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 			tagi = FPU_Special(r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 			fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		case TAG_Valid:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 			printk("st(%d)  %c .%04lx %04lx %04lx %04lx e%+-6d ", i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 			       getsign(r) ? '-' : '+',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 			       (long)(r->sigh >> 16),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 			       (long)(r->sigh & 0xFFFF),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 			       (long)(r->sigl >> 16),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 			       (long)(r->sigl & 0xFFFF),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 			       exponent(r) - EXP_BIAS + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 			printk("Whoops! Error in errors.c: tag%d is %d ", i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 			       tagi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 		printk("%s\n", tag_desc[(int)(unsigned)tagi]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	RE_ENTRANT_CHECK_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) static struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	int type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) } exception_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	EX_StackOver, "stack overflow"}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	EX_StackUnder, "stack underflow"}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	EX_Precision, "loss of precision"}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	EX_Underflow, "underflow"}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	EX_Overflow, "overflow"}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	EX_ZeroDiv, "divide by zero"}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	EX_Denormal, "denormalized operand"}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	EX_Invalid, "invalid operation"}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	EX_INTERNAL, "INTERNAL BUG in " FPU_VERSION}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	0, NULL}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)  EX_INTERNAL is always given with a code which indicates where the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)  error was detected.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)  Internal error types:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)        0x14   in fpu_etc.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)        0x1nn  in a *.c file:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)               0x101  in reg_add_sub.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)               0x102  in reg_mul.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)               0x104  in poly_atan.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)               0x105  in reg_mul.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)               0x107  in fpu_trig.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	      0x108  in reg_compare.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	      0x109  in reg_compare.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	      0x110  in reg_add_sub.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	      0x111  in fpe_entry.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	      0x112  in fpu_trig.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	      0x113  in errors.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	      0x115  in fpu_trig.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	      0x116  in fpu_trig.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	      0x117  in fpu_trig.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	      0x118  in fpu_trig.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	      0x119  in fpu_trig.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	      0x120  in poly_atan.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	      0x121  in reg_compare.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	      0x122  in reg_compare.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	      0x123  in reg_compare.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	      0x125  in fpu_trig.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	      0x126  in fpu_entry.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	      0x127  in poly_2xm1.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	      0x128  in fpu_entry.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	      0x129  in fpu_entry.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	      0x130  in get_address.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	      0x131  in get_address.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	      0x132  in get_address.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	      0x133  in get_address.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	      0x140  in load_store.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	      0x141  in load_store.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)               0x150  in poly_sin.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)               0x151  in poly_sin.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	      0x160  in reg_ld_str.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	      0x161  in reg_ld_str.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	      0x162  in reg_ld_str.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	      0x163  in reg_ld_str.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	      0x164  in reg_ld_str.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	      0x170  in fpu_tags.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	      0x171  in fpu_tags.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	      0x172  in fpu_tags.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	      0x180  in reg_convert.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)        0x2nn  in an *.S file:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)               0x201  in reg_u_add.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)               0x202  in reg_u_div.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)               0x203  in reg_u_div.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)               0x204  in reg_u_div.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)               0x205  in reg_u_mul.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)               0x206  in reg_u_sub.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)               0x207  in wm_sqrt.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	      0x208  in reg_div.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)               0x209  in reg_u_sub.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)               0x210  in reg_u_sub.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)               0x211  in reg_u_sub.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)               0x212  in reg_u_sub.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	      0x213  in wm_sqrt.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	      0x214  in wm_sqrt.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	      0x215  in wm_sqrt.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	      0x220  in reg_norm.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	      0x221  in reg_norm.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	      0x230  in reg_round.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	      0x231  in reg_round.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	      0x232  in reg_round.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	      0x233  in reg_round.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	      0x234  in reg_round.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	      0x235  in reg_round.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	      0x236  in reg_round.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	      0x240  in div_Xsig.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	      0x241  in div_Xsig.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	      0x242  in div_Xsig.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) asmlinkage __visible void FPU_exception(int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	int i, int_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	int_type = 0;		/* Needed only to stop compiler warnings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	if (n & EX_INTERNAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 		int_type = n - EX_INTERNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 		n = EX_INTERNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 		/* Set lots of exception bits! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 		partial_status |= (SW_Exc_Mask | SW_Summary | SW_Backward);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 		/* Extract only the bits which we use to set the status word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 		n &= (SW_Exc_Mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 		/* Set the corresponding exception bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 		partial_status |= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 		/* Set summary bits iff exception isn't masked */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 		if (partial_status & ~control_word & CW_Exceptions)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 			partial_status |= (SW_Summary | SW_Backward);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 		if (n & (SW_Stack_Fault | EX_Precision)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 			if (!(n & SW_C1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 				/* This bit distinguishes over- from underflow for a stack fault,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 				   and roundup from round-down for precision loss. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 				partial_status &= ~SW_C1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	RE_ENTRANT_CHECK_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	if ((~control_word & n & CW_Exceptions) || (n == EX_INTERNAL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 		/* Get a name string for error reporting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 		for (i = 0; exception_names[i].type; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 			if ((exception_names[i].type & n) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 			    exception_names[i].type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 		if (exception_names[i].type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) #ifdef PRINT_MESSAGES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 			printk("FP Exception: %s!\n", exception_names[i].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) #endif /* PRINT_MESSAGES */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 		} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 			printk("FPU emulator: Unknown Exception: 0x%04x!\n", n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 		if (n == EX_INTERNAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 			printk("FPU emulator: Internal error type 0x%04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 			       int_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 			FPU_printall();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) #ifdef PRINT_MESSAGES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 			FPU_printall();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) #endif /* PRINT_MESSAGES */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 		 * The 80486 generates an interrupt on the next non-control FPU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 		 * instruction. So we need some means of flagging it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 		 * We use the ES (Error Summary) bit for this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	RE_ENTRANT_CHECK_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) #ifdef __DEBUG__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	math_abort(FPU_info, SIGFPE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) #endif /* __DEBUG__ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) /* Real operation attempted on a NaN. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) /* Returns < 0 if the exception is unmasked */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) int real_1op_NaN(FPU_REG *a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	int signalling, isNaN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	isNaN = (exponent(a) == EXP_OVER) && (a->sigh & 0x80000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	/* The default result for the case of two "equal" NaNs (signs may
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	   differ) is chosen to reproduce 80486 behaviour */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	signalling = isNaN && !(a->sigh & 0x40000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	if (!signalling) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 		if (!isNaN) {	/* pseudo-NaN, or other unsupported? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 			if (control_word & CW_Invalid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 				/* Masked response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 				reg_copy(&CONST_QNaN, a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 			EXCEPTION(EX_Invalid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 			return (!(control_word & CW_Invalid) ? FPU_Exception :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 				0) | TAG_Special;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 		return TAG_Special;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 	if (control_word & CW_Invalid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 		/* The masked response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 		if (!(a->sigh & 0x80000000)) {	/* pseudo-NaN ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 			reg_copy(&CONST_QNaN, a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 		/* ensure a Quiet NaN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 		a->sigh |= 0x40000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	EXCEPTION(EX_Invalid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Special;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) /* Real operation attempted on two operands, one a NaN. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) /* Returns < 0 if the exception is unmasked */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) int real_2op_NaN(FPU_REG const *b, u_char tagb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 		 int deststnr, FPU_REG const *defaultNaN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 	FPU_REG *dest = &st(deststnr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 	FPU_REG const *a = dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	u_char taga = FPU_gettagi(deststnr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	FPU_REG const *x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 	int signalling, unsupported;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	if (taga == TAG_Special)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 		taga = FPU_Special(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	if (tagb == TAG_Special)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 		tagb = FPU_Special(b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 	/* TW_NaN is also used for unsupported data types. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 	unsupported = ((taga == TW_NaN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 		       && !((exponent(a) == EXP_OVER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 			    && (a->sigh & 0x80000000)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 	    || ((tagb == TW_NaN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 		&& !((exponent(b) == EXP_OVER) && (b->sigh & 0x80000000)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 	if (unsupported) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 		if (control_word & CW_Invalid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 			/* Masked response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 			FPU_copy_to_regi(&CONST_QNaN, TAG_Special, deststnr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 		EXCEPTION(EX_Invalid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 		return (!(control_word & CW_Invalid) ? FPU_Exception : 0) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 		    TAG_Special;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	if (taga == TW_NaN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 		x = a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 		if (tagb == TW_NaN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 			signalling = !(a->sigh & b->sigh & 0x40000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 			if (significand(b) > significand(a))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 				x = b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 			else if (significand(b) == significand(a)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 				/* The default result for the case of two "equal" NaNs (signs may
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 				   differ) is chosen to reproduce 80486 behaviour */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 				x = defaultNaN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 			/* return the quiet version of the NaN in a */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 			signalling = !(a->sigh & 0x40000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) #ifdef PARANOID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 	if (tagb == TW_NaN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) #endif /* PARANOID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 		signalling = !(b->sigh & 0x40000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 		x = b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) #ifdef PARANOID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 	else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 		signalling = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 		EXCEPTION(EX_INTERNAL | 0x113);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 		x = &CONST_QNaN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) #endif /* PARANOID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 	if ((!signalling) || (control_word & CW_Invalid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 		if (!x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 			x = b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 		if (!(x->sigh & 0x80000000))	/* pseudo-NaN ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 			x = &CONST_QNaN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 		FPU_copy_to_regi(x, TAG_Special, deststnr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 		if (!signalling)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 			return TAG_Special;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 		/* ensure a Quiet NaN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 		dest->sigh |= 0x40000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 	EXCEPTION(EX_Invalid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Special;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) /* Invalid arith operation on Valid registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) /* Returns < 0 if the exception is unmasked */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) asmlinkage __visible int arith_invalid(int deststnr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 	EXCEPTION(EX_Invalid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 	if (control_word & CW_Invalid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 		/* The masked response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 		FPU_copy_to_regi(&CONST_QNaN, TAG_Special, deststnr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 	return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) /* Divide a finite number by zero */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) asmlinkage __visible int FPU_divide_by_zero(int deststnr, u_char sign)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 	FPU_REG *dest = &st(deststnr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 	int tag = TAG_Valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 	if (control_word & CW_ZeroDiv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 		/* The masked response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 		FPU_copy_to_regi(&CONST_INF, TAG_Special, deststnr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 		setsign(dest, sign);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 		tag = TAG_Special;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 	EXCEPTION(EX_ZeroDiv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 	return (!(control_word & CW_ZeroDiv) ? FPU_Exception : 0) | tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) /* This may be called often, so keep it lean */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) int set_precision_flag(int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 	if (control_word & CW_Precision) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 		partial_status &= ~(SW_C1 & flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 		partial_status |= flags;	/* The masked response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 		EXCEPTION(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) /* This may be called often, so keep it lean */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) asmlinkage __visible void set_precision_flag_up(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 	if (control_word & CW_Precision)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 		partial_status |= (SW_Precision | SW_C1);	/* The masked response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 		EXCEPTION(EX_Precision | SW_C1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) /* This may be called often, so keep it lean */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) asmlinkage __visible void set_precision_flag_down(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 	if (control_word & CW_Precision) {	/* The masked response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 		partial_status &= ~SW_C1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 		partial_status |= SW_Precision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 		EXCEPTION(EX_Precision);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) asmlinkage __visible int denormal_operand(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 	if (control_word & CW_Denormal) {	/* The masked response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 		partial_status |= SW_Denorm_Op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 		return TAG_Special;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 		EXCEPTION(EX_Denormal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 		return TAG_Special | FPU_Exception;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) asmlinkage __visible int arith_overflow(FPU_REG *dest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 	int tag = TAG_Valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 	if (control_word & CW_Overflow) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 		/* The masked response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) /* ###### The response here depends upon the rounding mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 		reg_copy(&CONST_INF, dest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 		tag = TAG_Special;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 		/* Subtract the magic number from the exponent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 		addexponent(dest, (-3 * (1 << 13)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 	EXCEPTION(EX_Overflow);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 	if (control_word & CW_Overflow) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 		/* The overflow exception is masked. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 		/* By definition, precision is lost.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 		   The roundup bit (C1) is also set because we have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 		   "rounded" upwards to Infinity. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 		EXCEPTION(EX_Precision | SW_C1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 		return tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 	return tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) asmlinkage __visible int arith_underflow(FPU_REG *dest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 	int tag = TAG_Valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 	if (control_word & CW_Underflow) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 		/* The masked response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 		if (exponent16(dest) <= EXP_UNDER - 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 			reg_copy(&CONST_Z, dest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 			partial_status &= ~SW_C1;	/* Round down. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 			tag = TAG_Zero;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 			stdexp(dest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 		/* Add the magic number to the exponent. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 		addexponent(dest, (3 * (1 << 13)) + EXTENDED_Ebias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 	EXCEPTION(EX_Underflow);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 	if (control_word & CW_Underflow) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 		/* The underflow exception is masked. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 		EXCEPTION(EX_Precision);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 		return tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 	return tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) void FPU_stack_overflow(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 	if (control_word & CW_Invalid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 		/* The masked response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 		top--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 		FPU_copy_to_reg0(&CONST_QNaN, TAG_Special);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 	EXCEPTION(EX_StackOver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) void FPU_stack_underflow(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 	if (control_word & CW_Invalid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 		/* The masked response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 		FPU_copy_to_reg0(&CONST_QNaN, TAG_Special);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 	EXCEPTION(EX_StackUnder);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) void FPU_stack_underflow_i(int i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 	if (control_word & CW_Invalid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 		/* The masked response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 		FPU_copy_to_regi(&CONST_QNaN, TAG_Special, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 	EXCEPTION(EX_StackUnder);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) void FPU_stack_underflow_pop(int i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 	if (control_word & CW_Invalid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 		/* The masked response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 		FPU_copy_to_regi(&CONST_QNaN, TAG_Special, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 		FPU_pop();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 	EXCEPTION(EX_StackUnder);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) }