xref: /OK3568_Linux_fs/kernel/arch/x86/math-emu/fpu_etc.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*---------------------------------------------------------------------------+
3*4882a593Smuzhiyun  |  fpu_etc.c                                                                |
4*4882a593Smuzhiyun  |                                                                           |
5*4882a593Smuzhiyun  | Implement a few FPU instructions.                                         |
6*4882a593Smuzhiyun  |                                                                           |
7*4882a593Smuzhiyun  | Copyright (C) 1992,1993,1994,1997                                         |
8*4882a593Smuzhiyun  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
9*4882a593Smuzhiyun  |                       Australia.  E-mail   billm@suburbia.net             |
10*4882a593Smuzhiyun  |                                                                           |
11*4882a593Smuzhiyun  |                                                                           |
12*4882a593Smuzhiyun  +---------------------------------------------------------------------------*/
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #include "fpu_system.h"
15*4882a593Smuzhiyun #include "exception.h"
16*4882a593Smuzhiyun #include "fpu_emu.h"
17*4882a593Smuzhiyun #include "status_w.h"
18*4882a593Smuzhiyun #include "reg_constant.h"
19*4882a593Smuzhiyun 
fchs(FPU_REG * st0_ptr,u_char st0tag)20*4882a593Smuzhiyun static void fchs(FPU_REG *st0_ptr, u_char st0tag)
21*4882a593Smuzhiyun {
22*4882a593Smuzhiyun 	if (st0tag ^ TAG_Empty) {
23*4882a593Smuzhiyun 		signbyte(st0_ptr) ^= SIGN_NEG;
24*4882a593Smuzhiyun 		clear_C1();
25*4882a593Smuzhiyun 	} else
26*4882a593Smuzhiyun 		FPU_stack_underflow();
27*4882a593Smuzhiyun }
28*4882a593Smuzhiyun 
fabs(FPU_REG * st0_ptr,u_char st0tag)29*4882a593Smuzhiyun static void fabs(FPU_REG *st0_ptr, u_char st0tag)
30*4882a593Smuzhiyun {
31*4882a593Smuzhiyun 	if (st0tag ^ TAG_Empty) {
32*4882a593Smuzhiyun 		setpositive(st0_ptr);
33*4882a593Smuzhiyun 		clear_C1();
34*4882a593Smuzhiyun 	} else
35*4882a593Smuzhiyun 		FPU_stack_underflow();
36*4882a593Smuzhiyun }
37*4882a593Smuzhiyun 
ftst_(FPU_REG * st0_ptr,u_char st0tag)38*4882a593Smuzhiyun static void ftst_(FPU_REG *st0_ptr, u_char st0tag)
39*4882a593Smuzhiyun {
40*4882a593Smuzhiyun 	switch (st0tag) {
41*4882a593Smuzhiyun 	case TAG_Zero:
42*4882a593Smuzhiyun 		setcc(SW_C3);
43*4882a593Smuzhiyun 		break;
44*4882a593Smuzhiyun 	case TAG_Valid:
45*4882a593Smuzhiyun 		if (getsign(st0_ptr) == SIGN_POS)
46*4882a593Smuzhiyun 			setcc(0);
47*4882a593Smuzhiyun 		else
48*4882a593Smuzhiyun 			setcc(SW_C0);
49*4882a593Smuzhiyun 		break;
50*4882a593Smuzhiyun 	case TAG_Special:
51*4882a593Smuzhiyun 		switch (FPU_Special(st0_ptr)) {
52*4882a593Smuzhiyun 		case TW_Denormal:
53*4882a593Smuzhiyun 			if (getsign(st0_ptr) == SIGN_POS)
54*4882a593Smuzhiyun 				setcc(0);
55*4882a593Smuzhiyun 			else
56*4882a593Smuzhiyun 				setcc(SW_C0);
57*4882a593Smuzhiyun 			if (denormal_operand() < 0) {
58*4882a593Smuzhiyun #ifdef PECULIAR_486
59*4882a593Smuzhiyun 				/* This is weird! */
60*4882a593Smuzhiyun 				if (getsign(st0_ptr) == SIGN_POS)
61*4882a593Smuzhiyun 					setcc(SW_C3);
62*4882a593Smuzhiyun #endif /* PECULIAR_486 */
63*4882a593Smuzhiyun 				return;
64*4882a593Smuzhiyun 			}
65*4882a593Smuzhiyun 			break;
66*4882a593Smuzhiyun 		case TW_NaN:
67*4882a593Smuzhiyun 			setcc(SW_C0 | SW_C2 | SW_C3);	/* Operand is not comparable */
68*4882a593Smuzhiyun 			EXCEPTION(EX_Invalid);
69*4882a593Smuzhiyun 			break;
70*4882a593Smuzhiyun 		case TW_Infinity:
71*4882a593Smuzhiyun 			if (getsign(st0_ptr) == SIGN_POS)
72*4882a593Smuzhiyun 				setcc(0);
73*4882a593Smuzhiyun 			else
74*4882a593Smuzhiyun 				setcc(SW_C0);
75*4882a593Smuzhiyun 			break;
76*4882a593Smuzhiyun 		default:
77*4882a593Smuzhiyun 			setcc(SW_C0 | SW_C2 | SW_C3);	/* Operand is not comparable */
78*4882a593Smuzhiyun 			EXCEPTION(EX_INTERNAL | 0x14);
79*4882a593Smuzhiyun 			break;
80*4882a593Smuzhiyun 		}
81*4882a593Smuzhiyun 		break;
82*4882a593Smuzhiyun 	case TAG_Empty:
83*4882a593Smuzhiyun 		setcc(SW_C0 | SW_C2 | SW_C3);
84*4882a593Smuzhiyun 		EXCEPTION(EX_StackUnder);
85*4882a593Smuzhiyun 		break;
86*4882a593Smuzhiyun 	}
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun 
fxam(FPU_REG * st0_ptr,u_char st0tag)89*4882a593Smuzhiyun static void fxam(FPU_REG *st0_ptr, u_char st0tag)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun 	int c = 0;
92*4882a593Smuzhiyun 	switch (st0tag) {
93*4882a593Smuzhiyun 	case TAG_Empty:
94*4882a593Smuzhiyun 		c = SW_C3 | SW_C0;
95*4882a593Smuzhiyun 		break;
96*4882a593Smuzhiyun 	case TAG_Zero:
97*4882a593Smuzhiyun 		c = SW_C3;
98*4882a593Smuzhiyun 		break;
99*4882a593Smuzhiyun 	case TAG_Valid:
100*4882a593Smuzhiyun 		c = SW_C2;
101*4882a593Smuzhiyun 		break;
102*4882a593Smuzhiyun 	case TAG_Special:
103*4882a593Smuzhiyun 		switch (FPU_Special(st0_ptr)) {
104*4882a593Smuzhiyun 		case TW_Denormal:
105*4882a593Smuzhiyun 			c = SW_C2 | SW_C3;	/* Denormal */
106*4882a593Smuzhiyun 			break;
107*4882a593Smuzhiyun 		case TW_NaN:
108*4882a593Smuzhiyun 			/* We also use NaN for unsupported types. */
109*4882a593Smuzhiyun 			if ((st0_ptr->sigh & 0x80000000)
110*4882a593Smuzhiyun 			    && (exponent(st0_ptr) == EXP_OVER))
111*4882a593Smuzhiyun 				c = SW_C0;
112*4882a593Smuzhiyun 			break;
113*4882a593Smuzhiyun 		case TW_Infinity:
114*4882a593Smuzhiyun 			c = SW_C2 | SW_C0;
115*4882a593Smuzhiyun 			break;
116*4882a593Smuzhiyun 		}
117*4882a593Smuzhiyun 	}
118*4882a593Smuzhiyun 	if (getsign(st0_ptr) == SIGN_NEG)
119*4882a593Smuzhiyun 		c |= SW_C1;
120*4882a593Smuzhiyun 	setcc(c);
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun static FUNC_ST0 const fp_etc_table[] = {
124*4882a593Smuzhiyun 	fchs, fabs, (FUNC_ST0) FPU_illegal, (FUNC_ST0) FPU_illegal,
125*4882a593Smuzhiyun 	ftst_, fxam, (FUNC_ST0) FPU_illegal, (FUNC_ST0) FPU_illegal
126*4882a593Smuzhiyun };
127*4882a593Smuzhiyun 
FPU_etc(void)128*4882a593Smuzhiyun void FPU_etc(void)
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun 	(fp_etc_table[FPU_rm]) (&st(0), FPU_gettag0());
131*4882a593Smuzhiyun }
132