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 "control_w.h"
21 #include "status_w.h"
22
23
24 int compare(FPU_REG const *b)
25 {
26 int diff;
27
28 if ( FPU_st0_ptr->tag | b->tag )
29 {
30 if ( FPU_st0_ptr->tag == TW_Zero )
31 {
32 if ( b->tag == TW_Zero ) return COMP_A_eq_B;
33 if ( b->tag == TW_Valid )
34 {
35 return ((b->sign == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B)
36 #ifdef DENORM_OPERAND
37 | ((b->exp <= EXP_UNDER) ?
38 COMP_Denormal : 0)
39 #endif DENORM_OPERAND
40 ;
41 }
42 }
43 else if ( b->tag == TW_Zero )
44 {
45 if ( FPU_st0_ptr->tag == TW_Valid )
46 {
47 return ((FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B
48 : COMP_A_lt_B)
49 #ifdef DENORM_OPERAND
50 | ((FPU_st0_ptr->exp <= EXP_UNDER )
51 ? COMP_Denormal : 0 )
52 #endif DENORM_OPERAND
53 ;
54 }
55 }
56
57 if ( FPU_st0_ptr->tag == TW_Infinity )
58 {
59 if ( (b->tag == TW_Valid) || (b->tag == TW_Zero) )
60 {
61 return ((FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B
62 : COMP_A_lt_B)
63 #ifdef DENORM_OPERAND
64 | (((b->tag == TW_Valid) && (b->exp <= EXP_UNDER)) ?
65 COMP_Denormal : 0 )
66 #endif DENORM_OPERAND
67 ;
68 }
69 else if ( b->tag == TW_Infinity )
70 {
71
72 return (FPU_st0_ptr->sign == b->sign) ? COMP_A_eq_B :
73 ((FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B);
74 }
75
76 }
77 else if ( b->tag == TW_Infinity )
78 {
79 if ( (FPU_st0_ptr->tag == TW_Valid) || (FPU_st0_ptr->tag == TW_Zero) )
80 {
81 return ((b->sign == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B)
82 #ifdef DENORM_OPERAND
83 | (((FPU_st0_ptr->tag == TW_Valid)
84 && (FPU_st0_ptr->exp <= EXP_UNDER)) ?
85 COMP_Denormal : 0)
86 #endif DENORM_OPERAND
87 ;
88 }
89
90 }
91
92
93
94 if ( (FPU_st0_ptr->tag == TW_NaN) || (b->tag == TW_NaN) )
95 {
96 if ( ((FPU_st0_ptr->tag == TW_NaN) && !(FPU_st0_ptr->sigh & 0x40000000))
97 || ((b->tag == TW_NaN) && !(b->sigh & 0x40000000)) )
98
99 return COMP_No_Comp | COMP_SNaN | COMP_NaN;
100 else
101
102 return COMP_No_Comp | COMP_NaN;
103 }
104
105 EXCEPTION(EX_Invalid);
106 }
107
108 #ifdef PARANOID
109 if (!(FPU_st0_ptr->sigh & 0x80000000)) EXCEPTION(EX_Invalid);
110 if (!(b->sigh & 0x80000000)) EXCEPTION(EX_Invalid);
111 #endif PARANOID
112
113
114 if (FPU_st0_ptr->sign != b->sign)
115 {
116 return ((FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B)
117 #ifdef DENORM_OPERAND
118 |
119 ( ((FPU_st0_ptr->exp <= EXP_UNDER) || (b->exp <= EXP_UNDER)) ?
120 COMP_Denormal : 0)
121 #endif DENORM_OPERAND
122 ;
123 }
124
125 diff = FPU_st0_ptr->exp - b->exp;
126 if ( diff == 0 )
127 {
128 diff = FPU_st0_ptr->sigh - b->sigh;
129
130 if ( diff == 0 )
131 {
132 diff = FPU_st0_ptr->sigl > b->sigl;
133 if ( diff == 0 )
134 diff = -(FPU_st0_ptr->sigl < b->sigl);
135 }
136 }
137
138 if ( diff > 0 )
139 {
140 return ((FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B)
141 #ifdef DENORM_OPERAND
142 |
143 ( ((FPU_st0_ptr->exp <= EXP_UNDER) || (b->exp <= EXP_UNDER)) ?
144 COMP_Denormal : 0)
145 #endif DENORM_OPERAND
146 ;
147 }
148 if ( diff < 0 )
149 {
150 return ((FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B)
151 #ifdef DENORM_OPERAND
152 |
153 ( ((FPU_st0_ptr->exp <= EXP_UNDER) || (b->exp <= EXP_UNDER)) ?
154 COMP_Denormal : 0)
155 #endif DENORM_OPERAND
156 ;
157 }
158
159 return COMP_A_eq_B
160 #ifdef DENORM_OPERAND
161 |
162 ( ((FPU_st0_ptr->exp <= EXP_UNDER) || (b->exp <= EXP_UNDER)) ?
163 COMP_Denormal : 0)
164 #endif DENORM_OPERAND
165 ;
166
167 }
168
169
170
171 int compare_st_data(void)
172 {
173 int f, c;
174
175 c = compare(&FPU_loaded_data);
176
177 if (c & COMP_NaN)
178 {
179 EXCEPTION(EX_Invalid);
180 f = SW_C3 | SW_C2 | SW_C0;
181 }
182 else
183 switch (c & 7)
184 {
185 case COMP_A_lt_B:
186 f = SW_C0;
187 break;
188 case COMP_A_eq_B:
189 f = SW_C3;
190 break;
191 case COMP_A_gt_B:
192 f = 0;
193 break;
194 case COMP_No_Comp:
195 f = SW_C3 | SW_C2 | SW_C0;
196 break;
197 #ifdef PARANOID
198 default:
199 EXCEPTION(EX_INTERNAL|0x121);
200 f = SW_C3 | SW_C2 | SW_C0;
201 break;
202 #endif PARANOID
203 }
204 setcc(f);
205 if (c & COMP_Denormal)
206 {
207 return denormal_operand();
208 }
209 return 0;
210 }
211
212
213 static int compare_st_st(int nr)
214 {
215 int f, c;
216
217 if ( !NOT_EMPTY_0 || !NOT_EMPTY(nr) )
218 {
219 setcc(SW_C3 | SW_C2 | SW_C0);
220
221 EXCEPTION(EX_StackUnder);
222 return !(control_word & CW_Invalid);
223 }
224
225 c = compare(&st(nr));
226 if (c & COMP_NaN)
227 {
228 setcc(SW_C3 | SW_C2 | SW_C0);
229 EXCEPTION(EX_Invalid);
230 return !(control_word & CW_Invalid);
231 }
232 else
233 switch (c & 7)
234 {
235 case COMP_A_lt_B:
236 f = SW_C0;
237 break;
238 case COMP_A_eq_B:
239 f = SW_C3;
240 break;
241 case COMP_A_gt_B:
242 f = 0;
243 break;
244 case COMP_No_Comp:
245 f = SW_C3 | SW_C2 | SW_C0;
246 break;
247 #ifdef PARANOID
248 default:
249 EXCEPTION(EX_INTERNAL|0x122);
250 f = SW_C3 | SW_C2 | SW_C0;
251 break;
252 #endif PARANOID
253 }
254 setcc(f);
255 if (c & COMP_Denormal)
256 {
257 return denormal_operand();
258 }
259 return 0;
260 }
261
262
263 static int compare_u_st_st(int nr)
264 {
265 int f, c;
266
267 if ( !NOT_EMPTY_0 || !NOT_EMPTY(nr) )
268 {
269 setcc(SW_C3 | SW_C2 | SW_C0);
270
271 EXCEPTION(EX_StackUnder);
272 return !(control_word & CW_Invalid);
273 }
274
275 c = compare(&st(nr));
276 if (c & COMP_NaN)
277 {
278 setcc(SW_C3 | SW_C2 | SW_C0);
279 if (c & COMP_SNaN)
280
281 {
282 EXCEPTION(EX_Invalid);
283 return !(control_word & CW_Invalid);
284 }
285 return 0;
286 }
287 else
288 switch (c & 7)
289 {
290 case COMP_A_lt_B:
291 f = SW_C0;
292 break;
293 case COMP_A_eq_B:
294 f = SW_C3;
295 break;
296 case COMP_A_gt_B:
297 f = 0;
298 break;
299 case COMP_No_Comp:
300 f = SW_C3 | SW_C2 | SW_C0;
301 break;
302 #ifdef PARANOID
303 default:
304 EXCEPTION(EX_INTERNAL|0x123);
305 f = SW_C3 | SW_C2 | SW_C0;
306 break;
307 #endif PARANOID
308 }
309 setcc(f);
310 if (c & COMP_Denormal)
311 {
312 return denormal_operand();
313 }
314 return 0;
315 }
316
317
318
319 void fcom_st()
320 {
321
322 compare_st_st(FPU_rm);
323 }
324
325
326 void fcompst()
327 {
328
329 if ( !compare_st_st(FPU_rm) )
330 pop();
331 }
332
333
334 void fcompp()
335 {
336
337 if (FPU_rm != 1)
338 {
339 Un_impl();
340 return;
341 }
342 if ( !compare_st_st(1) )
343 {
344 pop(); FPU_st0_ptr = &st(0);
345 pop();
346 }
347 }
348
349
350 void fucom_()
351 {
352
353 compare_u_st_st(FPU_rm);
354
355 }
356
357
358 void fucomp()
359 {
360
361 if ( !compare_u_st_st(FPU_rm) )
362 pop();
363 }
364
365
366 void fucompp()
367 {
368
369 if (FPU_rm == 1)
370 {
371 if ( !compare_u_st_st(1) )
372 {
373 pop(); FPU_st0_ptr = &st(0);
374 pop();
375 }
376 }
377 else
378 Un_impl();
379 }