This source file includes following definitions.
- compare
- compare_st_data
- compare_st_st
- compare_u_st_st
- fcom_st
- fcompst
- fcompp
- fucom_
- fucomp
- fucompp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 #include "fpu_system.h"
18 #include "exception.h"
19 #include "fpu_emu.h"
20 #include "status_w.h"
21
22
23 int compare(FPU_REG *b)
24 {
25 int diff;
26
27 if ( FPU_st0_ptr->tag | b->tag )
28 {
29 if ( FPU_st0_ptr->tag == TW_Zero )
30 {
31 if ( b->tag == TW_Zero ) return COMP_A_EQ_B;
32 if ( b->tag == TW_Valid )
33 {
34 return (b->sign == SIGN_POS) ? COMP_A_LT_B : COMP_A_GT_B ;
35 }
36 }
37 else if ( b->tag == TW_Zero )
38 {
39 if ( FPU_st0_ptr->tag == TW_Valid )
40 {
41 return (FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_GT_B : COMP_A_LT_B ;
42 }
43 }
44
45 if ( FPU_st0_ptr->tag == TW_Infinity )
46 {
47 if ( (b->tag == TW_Valid) || (b->tag == TW_Zero) )
48 {
49 return (FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_GT_B : COMP_A_LT_B;
50 }
51 else if ( b->tag == TW_Infinity )
52 {
53
54 return (FPU_st0_ptr->sign == b->sign) ? COMP_A_EQ_B :
55 ((FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_GT_B : COMP_A_LT_B);
56 }
57
58 }
59 else if ( b->tag == TW_Infinity )
60 {
61 if ( (FPU_st0_ptr->tag == TW_Valid) || (FPU_st0_ptr->tag == TW_Zero) )
62 {
63 return (b->sign == SIGN_POS) ? COMP_A_LT_B : COMP_A_GT_B;
64 }
65
66 }
67
68
69
70 if ( (FPU_st0_ptr->tag == TW_NaN) || (b->tag == TW_NaN) )
71 {
72 if ( ((FPU_st0_ptr->tag == TW_NaN) && !(FPU_st0_ptr->sigh & 0x40000000))
73 || ((b->tag == TW_NaN) && !(b->sigh & 0x40000000)) )
74
75 return COMP_NOCOMP | COMP_SNAN | COMP_NAN;
76 else
77
78 return COMP_NOCOMP | COMP_NAN;
79 }
80
81 EXCEPTION(EX_Invalid);
82 }
83
84 #ifdef PARANOID
85 if (!(FPU_st0_ptr->sigh & 0x80000000)) EXCEPTION(EX_Invalid);
86 if (!(b->sigh & 0x80000000)) EXCEPTION(EX_Invalid);
87 #endif PARANOID
88
89 if (FPU_st0_ptr->sign != b->sign)
90 return (FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_GT_B : COMP_A_LT_B;
91
92 diff = FPU_st0_ptr->exp - b->exp;
93 if ( diff == 0 )
94 {
95 diff = FPU_st0_ptr->sigh - b->sigh;
96
97 if ( diff == 0 )
98 {
99 diff = FPU_st0_ptr->sigl > b->sigl;
100 if ( diff == 0 )
101 diff = -(FPU_st0_ptr->sigl < b->sigl);
102 }
103 }
104
105 if ( diff > 0 )
106 return (FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_GT_B : COMP_A_LT_B ;
107 if ( diff < 0 )
108 return (FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_LT_B : COMP_A_GT_B ;
109 return COMP_A_EQ_B;
110
111 }
112
113
114 void compare_st_data(void)
115 {
116 int f;
117 int c = compare(&FPU_loaded_data);
118
119 if (c & COMP_NAN)
120 {
121 EXCEPTION(EX_Invalid);
122 f = SW_C3 | SW_C2 | SW_C0;
123 }
124 else
125 switch (c)
126 {
127 case COMP_A_LT_B:
128 f = SW_C0;
129 break;
130 case COMP_A_EQ_B:
131 f = SW_C3;
132 break;
133 case COMP_A_GT_B:
134 f = 0;
135 break;
136 case COMP_NOCOMP:
137 f = SW_C3 | SW_C2 | SW_C0;
138 break;
139 #ifdef PARANOID
140 default:
141 EXCEPTION(EX_INTERNAL|0x121);
142 f = SW_C3 | SW_C2 | SW_C0;
143 break;
144 #endif PARANOID
145 }
146 setcc(f);
147 }
148
149
150 static void compare_st_st(int nr)
151 {
152 int c = compare(&st(nr));
153 int f;
154 if (c & COMP_NAN)
155 {
156 EXCEPTION(EX_Invalid);
157 f = SW_C3 | SW_C2 | SW_C0;
158 }
159 else
160 switch (c)
161 {
162 case COMP_A_LT_B:
163 f = SW_C0;
164 break;
165 case COMP_A_EQ_B:
166 f = SW_C3;
167 break;
168 case COMP_A_GT_B:
169 f = 0;
170 break;
171 case COMP_NOCOMP:
172 f = SW_C3 | SW_C2 | SW_C0;
173 break;
174 #ifdef PARANOID
175 default:
176 EXCEPTION(EX_INTERNAL|0x122);
177 f = SW_C3 | SW_C2 | SW_C0;
178 break;
179 #endif PARANOID
180 }
181 setcc(f);
182 }
183
184
185 static void compare_u_st_st(int nr)
186 {
187 int f;
188 int c = compare(&st(nr));
189 if (c & COMP_NAN)
190 {
191 if (c & COMP_SNAN)
192
193 EXCEPTION(EX_Invalid);
194 f = SW_C3 | SW_C2 | SW_C0;
195 }
196 else
197 switch (c)
198 {
199 case COMP_A_LT_B:
200 f = SW_C0;
201 break;
202 case COMP_A_EQ_B:
203 f = SW_C3;
204 break;
205 case COMP_A_GT_B:
206 f = 0;
207 break;
208 case COMP_NOCOMP:
209 f = SW_C3 | SW_C2 | SW_C0;
210 break;
211 #ifdef PARANOID
212 default:
213 EXCEPTION(EX_INTERNAL|0x123);
214 f = SW_C3 | SW_C2 | SW_C0;
215 break;
216 #endif PARANOID
217 }
218 setcc(f);
219 }
220
221
222
223 void fcom_st()
224 {
225
226 compare_st_st(FPU_rm);
227 }
228
229
230 void fcompst()
231 {
232
233 compare_st_st(FPU_rm);
234 pop();
235 }
236
237
238 void fcompp()
239 {
240
241 if (FPU_rm != 1)
242 return Un_impl();
243 compare_st_st(1);
244 pop(); FPU_st0_ptr = &st(0);
245 pop();
246 }
247
248
249 void fucom_()
250 {
251
252 compare_u_st_st(FPU_rm);
253 }
254
255
256 void fucomp()
257 {
258
259 compare_u_st_st(FPU_rm);
260 pop();
261 }
262
263
264 void fucompp()
265 {
266
267 if (FPU_rm == 1)
268 {
269 compare_u_st_st(1);
270 pop(); FPU_st0_ptr = &st(0);
271 pop();
272 }
273 else
274 Un_impl();
275 }