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