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