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