1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*---------------------------------------------------------------------------+
3*4882a593Smuzhiyun | reg_compare.c |
4*4882a593Smuzhiyun | |
5*4882a593Smuzhiyun | Compare two floating point registers |
6*4882a593Smuzhiyun | |
7*4882a593Smuzhiyun | Copyright (C) 1992,1993,1994,1997 |
8*4882a593Smuzhiyun | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
9*4882a593Smuzhiyun | E-mail billm@suburbia.net |
10*4882a593Smuzhiyun | |
11*4882a593Smuzhiyun | |
12*4882a593Smuzhiyun +---------------------------------------------------------------------------*/
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun /*---------------------------------------------------------------------------+
15*4882a593Smuzhiyun | compare() is the core FPU_REG comparison function |
16*4882a593Smuzhiyun +---------------------------------------------------------------------------*/
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun #include "fpu_system.h"
19*4882a593Smuzhiyun #include "exception.h"
20*4882a593Smuzhiyun #include "fpu_emu.h"
21*4882a593Smuzhiyun #include "control_w.h"
22*4882a593Smuzhiyun #include "status_w.h"
23*4882a593Smuzhiyun
compare(FPU_REG const * b,int tagb)24*4882a593Smuzhiyun static int compare(FPU_REG const *b, int tagb)
25*4882a593Smuzhiyun {
26*4882a593Smuzhiyun int diff, exp0, expb;
27*4882a593Smuzhiyun u_char st0_tag;
28*4882a593Smuzhiyun FPU_REG *st0_ptr;
29*4882a593Smuzhiyun FPU_REG x, y;
30*4882a593Smuzhiyun u_char st0_sign, signb = getsign(b);
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun st0_ptr = &st(0);
33*4882a593Smuzhiyun st0_tag = FPU_gettag0();
34*4882a593Smuzhiyun st0_sign = getsign(st0_ptr);
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun if (tagb == TAG_Special)
37*4882a593Smuzhiyun tagb = FPU_Special(b);
38*4882a593Smuzhiyun if (st0_tag == TAG_Special)
39*4882a593Smuzhiyun st0_tag = FPU_Special(st0_ptr);
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun if (((st0_tag != TAG_Valid) && (st0_tag != TW_Denormal))
42*4882a593Smuzhiyun || ((tagb != TAG_Valid) && (tagb != TW_Denormal))) {
43*4882a593Smuzhiyun if (st0_tag == TAG_Zero) {
44*4882a593Smuzhiyun if (tagb == TAG_Zero)
45*4882a593Smuzhiyun return COMP_A_eq_B;
46*4882a593Smuzhiyun if (tagb == TAG_Valid)
47*4882a593Smuzhiyun return ((signb ==
48*4882a593Smuzhiyun SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B);
49*4882a593Smuzhiyun if (tagb == TW_Denormal)
50*4882a593Smuzhiyun return ((signb ==
51*4882a593Smuzhiyun SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B)
52*4882a593Smuzhiyun | COMP_Denormal;
53*4882a593Smuzhiyun } else if (tagb == TAG_Zero) {
54*4882a593Smuzhiyun if (st0_tag == TAG_Valid)
55*4882a593Smuzhiyun return ((st0_sign ==
56*4882a593Smuzhiyun SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B);
57*4882a593Smuzhiyun if (st0_tag == TW_Denormal)
58*4882a593Smuzhiyun return ((st0_sign ==
59*4882a593Smuzhiyun SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B)
60*4882a593Smuzhiyun | COMP_Denormal;
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun if (st0_tag == TW_Infinity) {
64*4882a593Smuzhiyun if ((tagb == TAG_Valid) || (tagb == TAG_Zero))
65*4882a593Smuzhiyun return ((st0_sign ==
66*4882a593Smuzhiyun SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B);
67*4882a593Smuzhiyun else if (tagb == TW_Denormal)
68*4882a593Smuzhiyun return ((st0_sign ==
69*4882a593Smuzhiyun SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B)
70*4882a593Smuzhiyun | COMP_Denormal;
71*4882a593Smuzhiyun else if (tagb == TW_Infinity) {
72*4882a593Smuzhiyun /* The 80486 book says that infinities can be equal! */
73*4882a593Smuzhiyun return (st0_sign == signb) ? COMP_A_eq_B :
74*4882a593Smuzhiyun ((st0_sign ==
75*4882a593Smuzhiyun SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B);
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun /* Fall through to the NaN code */
78*4882a593Smuzhiyun } else if (tagb == TW_Infinity) {
79*4882a593Smuzhiyun if ((st0_tag == TAG_Valid) || (st0_tag == TAG_Zero))
80*4882a593Smuzhiyun return ((signb ==
81*4882a593Smuzhiyun SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B);
82*4882a593Smuzhiyun if (st0_tag == TW_Denormal)
83*4882a593Smuzhiyun return ((signb ==
84*4882a593Smuzhiyun SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B)
85*4882a593Smuzhiyun | COMP_Denormal;
86*4882a593Smuzhiyun /* Fall through to the NaN code */
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun /* The only possibility now should be that one of the arguments
90*4882a593Smuzhiyun is a NaN */
91*4882a593Smuzhiyun if ((st0_tag == TW_NaN) || (tagb == TW_NaN)) {
92*4882a593Smuzhiyun int signalling = 0, unsupported = 0;
93*4882a593Smuzhiyun if (st0_tag == TW_NaN) {
94*4882a593Smuzhiyun signalling =
95*4882a593Smuzhiyun (st0_ptr->sigh & 0xc0000000) == 0x80000000;
96*4882a593Smuzhiyun unsupported = !((exponent(st0_ptr) == EXP_OVER)
97*4882a593Smuzhiyun && (st0_ptr->
98*4882a593Smuzhiyun sigh & 0x80000000));
99*4882a593Smuzhiyun }
100*4882a593Smuzhiyun if (tagb == TW_NaN) {
101*4882a593Smuzhiyun signalling |=
102*4882a593Smuzhiyun (b->sigh & 0xc0000000) == 0x80000000;
103*4882a593Smuzhiyun unsupported |= !((exponent(b) == EXP_OVER)
104*4882a593Smuzhiyun && (b->sigh & 0x80000000));
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun if (signalling || unsupported)
107*4882a593Smuzhiyun return COMP_No_Comp | COMP_SNaN | COMP_NaN;
108*4882a593Smuzhiyun else
109*4882a593Smuzhiyun /* Neither is a signaling NaN */
110*4882a593Smuzhiyun return COMP_No_Comp | COMP_NaN;
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun EXCEPTION(EX_Invalid);
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun if (st0_sign != signb) {
117*4882a593Smuzhiyun return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B)
118*4882a593Smuzhiyun | (((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ?
119*4882a593Smuzhiyun COMP_Denormal : 0);
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun if ((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) {
123*4882a593Smuzhiyun FPU_to_exp16(st0_ptr, &x);
124*4882a593Smuzhiyun FPU_to_exp16(b, &y);
125*4882a593Smuzhiyun st0_ptr = &x;
126*4882a593Smuzhiyun b = &y;
127*4882a593Smuzhiyun exp0 = exponent16(st0_ptr);
128*4882a593Smuzhiyun expb = exponent16(b);
129*4882a593Smuzhiyun } else {
130*4882a593Smuzhiyun exp0 = exponent(st0_ptr);
131*4882a593Smuzhiyun expb = exponent(b);
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun #ifdef PARANOID
135*4882a593Smuzhiyun if (!(st0_ptr->sigh & 0x80000000))
136*4882a593Smuzhiyun EXCEPTION(EX_Invalid);
137*4882a593Smuzhiyun if (!(b->sigh & 0x80000000))
138*4882a593Smuzhiyun EXCEPTION(EX_Invalid);
139*4882a593Smuzhiyun #endif /* PARANOID */
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun diff = exp0 - expb;
142*4882a593Smuzhiyun if (diff == 0) {
143*4882a593Smuzhiyun diff = st0_ptr->sigh - b->sigh; /* Works only if ms bits are
144*4882a593Smuzhiyun identical */
145*4882a593Smuzhiyun if (diff == 0) {
146*4882a593Smuzhiyun diff = st0_ptr->sigl > b->sigl;
147*4882a593Smuzhiyun if (diff == 0)
148*4882a593Smuzhiyun diff = -(st0_ptr->sigl < b->sigl);
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun if (diff > 0) {
153*4882a593Smuzhiyun return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B)
154*4882a593Smuzhiyun | (((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ?
155*4882a593Smuzhiyun COMP_Denormal : 0);
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun if (diff < 0) {
158*4882a593Smuzhiyun return ((st0_sign == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B)
159*4882a593Smuzhiyun | (((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ?
160*4882a593Smuzhiyun COMP_Denormal : 0);
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun return COMP_A_eq_B
164*4882a593Smuzhiyun | (((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ?
165*4882a593Smuzhiyun COMP_Denormal : 0);
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun /* This function requires that st(0) is not empty */
FPU_compare_st_data(FPU_REG const * loaded_data,u_char loaded_tag)170*4882a593Smuzhiyun int FPU_compare_st_data(FPU_REG const *loaded_data, u_char loaded_tag)
171*4882a593Smuzhiyun {
172*4882a593Smuzhiyun int f, c;
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun c = compare(loaded_data, loaded_tag);
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun if (c & COMP_NaN) {
177*4882a593Smuzhiyun EXCEPTION(EX_Invalid);
178*4882a593Smuzhiyun f = SW_C3 | SW_C2 | SW_C0;
179*4882a593Smuzhiyun } else
180*4882a593Smuzhiyun switch (c & 7) {
181*4882a593Smuzhiyun case COMP_A_lt_B:
182*4882a593Smuzhiyun f = SW_C0;
183*4882a593Smuzhiyun break;
184*4882a593Smuzhiyun case COMP_A_eq_B:
185*4882a593Smuzhiyun f = SW_C3;
186*4882a593Smuzhiyun break;
187*4882a593Smuzhiyun case COMP_A_gt_B:
188*4882a593Smuzhiyun f = 0;
189*4882a593Smuzhiyun break;
190*4882a593Smuzhiyun case COMP_No_Comp:
191*4882a593Smuzhiyun f = SW_C3 | SW_C2 | SW_C0;
192*4882a593Smuzhiyun break;
193*4882a593Smuzhiyun default:
194*4882a593Smuzhiyun #ifdef PARANOID
195*4882a593Smuzhiyun EXCEPTION(EX_INTERNAL | 0x121);
196*4882a593Smuzhiyun #endif /* PARANOID */
197*4882a593Smuzhiyun f = SW_C3 | SW_C2 | SW_C0;
198*4882a593Smuzhiyun break;
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun setcc(f);
201*4882a593Smuzhiyun if (c & COMP_Denormal) {
202*4882a593Smuzhiyun return denormal_operand() < 0;
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun return 0;
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun
compare_st_st(int nr)207*4882a593Smuzhiyun static int compare_st_st(int nr)
208*4882a593Smuzhiyun {
209*4882a593Smuzhiyun int f, c;
210*4882a593Smuzhiyun FPU_REG *st_ptr;
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun if (!NOT_EMPTY(0) || !NOT_EMPTY(nr)) {
213*4882a593Smuzhiyun setcc(SW_C3 | SW_C2 | SW_C0);
214*4882a593Smuzhiyun /* Stack fault */
215*4882a593Smuzhiyun EXCEPTION(EX_StackUnder);
216*4882a593Smuzhiyun return !(control_word & CW_Invalid);
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun st_ptr = &st(nr);
220*4882a593Smuzhiyun c = compare(st_ptr, FPU_gettagi(nr));
221*4882a593Smuzhiyun if (c & COMP_NaN) {
222*4882a593Smuzhiyun setcc(SW_C3 | SW_C2 | SW_C0);
223*4882a593Smuzhiyun EXCEPTION(EX_Invalid);
224*4882a593Smuzhiyun return !(control_word & CW_Invalid);
225*4882a593Smuzhiyun } else
226*4882a593Smuzhiyun switch (c & 7) {
227*4882a593Smuzhiyun case COMP_A_lt_B:
228*4882a593Smuzhiyun f = SW_C0;
229*4882a593Smuzhiyun break;
230*4882a593Smuzhiyun case COMP_A_eq_B:
231*4882a593Smuzhiyun f = SW_C3;
232*4882a593Smuzhiyun break;
233*4882a593Smuzhiyun case COMP_A_gt_B:
234*4882a593Smuzhiyun f = 0;
235*4882a593Smuzhiyun break;
236*4882a593Smuzhiyun case COMP_No_Comp:
237*4882a593Smuzhiyun f = SW_C3 | SW_C2 | SW_C0;
238*4882a593Smuzhiyun break;
239*4882a593Smuzhiyun default:
240*4882a593Smuzhiyun #ifdef PARANOID
241*4882a593Smuzhiyun EXCEPTION(EX_INTERNAL | 0x122);
242*4882a593Smuzhiyun #endif /* PARANOID */
243*4882a593Smuzhiyun f = SW_C3 | SW_C2 | SW_C0;
244*4882a593Smuzhiyun break;
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun setcc(f);
247*4882a593Smuzhiyun if (c & COMP_Denormal) {
248*4882a593Smuzhiyun return denormal_operand() < 0;
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun return 0;
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun
compare_i_st_st(int nr)253*4882a593Smuzhiyun static int compare_i_st_st(int nr)
254*4882a593Smuzhiyun {
255*4882a593Smuzhiyun int f, c;
256*4882a593Smuzhiyun FPU_REG *st_ptr;
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun if (!NOT_EMPTY(0) || !NOT_EMPTY(nr)) {
259*4882a593Smuzhiyun FPU_EFLAGS |= (X86_EFLAGS_ZF | X86_EFLAGS_PF | X86_EFLAGS_CF);
260*4882a593Smuzhiyun /* Stack fault */
261*4882a593Smuzhiyun EXCEPTION(EX_StackUnder);
262*4882a593Smuzhiyun return !(control_word & CW_Invalid);
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun partial_status &= ~SW_C0;
266*4882a593Smuzhiyun st_ptr = &st(nr);
267*4882a593Smuzhiyun c = compare(st_ptr, FPU_gettagi(nr));
268*4882a593Smuzhiyun if (c & COMP_NaN) {
269*4882a593Smuzhiyun FPU_EFLAGS |= (X86_EFLAGS_ZF | X86_EFLAGS_PF | X86_EFLAGS_CF);
270*4882a593Smuzhiyun EXCEPTION(EX_Invalid);
271*4882a593Smuzhiyun return !(control_word & CW_Invalid);
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun switch (c & 7) {
275*4882a593Smuzhiyun case COMP_A_lt_B:
276*4882a593Smuzhiyun f = X86_EFLAGS_CF;
277*4882a593Smuzhiyun break;
278*4882a593Smuzhiyun case COMP_A_eq_B:
279*4882a593Smuzhiyun f = X86_EFLAGS_ZF;
280*4882a593Smuzhiyun break;
281*4882a593Smuzhiyun case COMP_A_gt_B:
282*4882a593Smuzhiyun f = 0;
283*4882a593Smuzhiyun break;
284*4882a593Smuzhiyun case COMP_No_Comp:
285*4882a593Smuzhiyun f = X86_EFLAGS_ZF | X86_EFLAGS_PF | X86_EFLAGS_CF;
286*4882a593Smuzhiyun break;
287*4882a593Smuzhiyun default:
288*4882a593Smuzhiyun #ifdef PARANOID
289*4882a593Smuzhiyun EXCEPTION(EX_INTERNAL | 0x122);
290*4882a593Smuzhiyun #endif /* PARANOID */
291*4882a593Smuzhiyun f = 0;
292*4882a593Smuzhiyun break;
293*4882a593Smuzhiyun }
294*4882a593Smuzhiyun FPU_EFLAGS = (FPU_EFLAGS & ~(X86_EFLAGS_ZF | X86_EFLAGS_PF | X86_EFLAGS_CF)) | f;
295*4882a593Smuzhiyun if (c & COMP_Denormal) {
296*4882a593Smuzhiyun return denormal_operand() < 0;
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun return 0;
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun
compare_u_st_st(int nr)301*4882a593Smuzhiyun static int compare_u_st_st(int nr)
302*4882a593Smuzhiyun {
303*4882a593Smuzhiyun int f = 0, c;
304*4882a593Smuzhiyun FPU_REG *st_ptr;
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun if (!NOT_EMPTY(0) || !NOT_EMPTY(nr)) {
307*4882a593Smuzhiyun setcc(SW_C3 | SW_C2 | SW_C0);
308*4882a593Smuzhiyun /* Stack fault */
309*4882a593Smuzhiyun EXCEPTION(EX_StackUnder);
310*4882a593Smuzhiyun return !(control_word & CW_Invalid);
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun st_ptr = &st(nr);
314*4882a593Smuzhiyun c = compare(st_ptr, FPU_gettagi(nr));
315*4882a593Smuzhiyun if (c & COMP_NaN) {
316*4882a593Smuzhiyun setcc(SW_C3 | SW_C2 | SW_C0);
317*4882a593Smuzhiyun if (c & COMP_SNaN) { /* This is the only difference between
318*4882a593Smuzhiyun un-ordered and ordinary comparisons */
319*4882a593Smuzhiyun EXCEPTION(EX_Invalid);
320*4882a593Smuzhiyun return !(control_word & CW_Invalid);
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun return 0;
323*4882a593Smuzhiyun } else
324*4882a593Smuzhiyun switch (c & 7) {
325*4882a593Smuzhiyun case COMP_A_lt_B:
326*4882a593Smuzhiyun f = SW_C0;
327*4882a593Smuzhiyun break;
328*4882a593Smuzhiyun case COMP_A_eq_B:
329*4882a593Smuzhiyun f = SW_C3;
330*4882a593Smuzhiyun break;
331*4882a593Smuzhiyun case COMP_A_gt_B:
332*4882a593Smuzhiyun f = 0;
333*4882a593Smuzhiyun break;
334*4882a593Smuzhiyun case COMP_No_Comp:
335*4882a593Smuzhiyun f = SW_C3 | SW_C2 | SW_C0;
336*4882a593Smuzhiyun break;
337*4882a593Smuzhiyun #ifdef PARANOID
338*4882a593Smuzhiyun default:
339*4882a593Smuzhiyun EXCEPTION(EX_INTERNAL | 0x123);
340*4882a593Smuzhiyun f = SW_C3 | SW_C2 | SW_C0;
341*4882a593Smuzhiyun break;
342*4882a593Smuzhiyun #endif /* PARANOID */
343*4882a593Smuzhiyun }
344*4882a593Smuzhiyun setcc(f);
345*4882a593Smuzhiyun if (c & COMP_Denormal) {
346*4882a593Smuzhiyun return denormal_operand() < 0;
347*4882a593Smuzhiyun }
348*4882a593Smuzhiyun return 0;
349*4882a593Smuzhiyun }
350*4882a593Smuzhiyun
compare_ui_st_st(int nr)351*4882a593Smuzhiyun static int compare_ui_st_st(int nr)
352*4882a593Smuzhiyun {
353*4882a593Smuzhiyun int f = 0, c;
354*4882a593Smuzhiyun FPU_REG *st_ptr;
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun if (!NOT_EMPTY(0) || !NOT_EMPTY(nr)) {
357*4882a593Smuzhiyun FPU_EFLAGS |= (X86_EFLAGS_ZF | X86_EFLAGS_PF | X86_EFLAGS_CF);
358*4882a593Smuzhiyun /* Stack fault */
359*4882a593Smuzhiyun EXCEPTION(EX_StackUnder);
360*4882a593Smuzhiyun return !(control_word & CW_Invalid);
361*4882a593Smuzhiyun }
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun partial_status &= ~SW_C0;
364*4882a593Smuzhiyun st_ptr = &st(nr);
365*4882a593Smuzhiyun c = compare(st_ptr, FPU_gettagi(nr));
366*4882a593Smuzhiyun if (c & COMP_NaN) {
367*4882a593Smuzhiyun FPU_EFLAGS |= (X86_EFLAGS_ZF | X86_EFLAGS_PF | X86_EFLAGS_CF);
368*4882a593Smuzhiyun if (c & COMP_SNaN) { /* This is the only difference between
369*4882a593Smuzhiyun un-ordered and ordinary comparisons */
370*4882a593Smuzhiyun EXCEPTION(EX_Invalid);
371*4882a593Smuzhiyun return !(control_word & CW_Invalid);
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun return 0;
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun
376*4882a593Smuzhiyun switch (c & 7) {
377*4882a593Smuzhiyun case COMP_A_lt_B:
378*4882a593Smuzhiyun f = X86_EFLAGS_CF;
379*4882a593Smuzhiyun break;
380*4882a593Smuzhiyun case COMP_A_eq_B:
381*4882a593Smuzhiyun f = X86_EFLAGS_ZF;
382*4882a593Smuzhiyun break;
383*4882a593Smuzhiyun case COMP_A_gt_B:
384*4882a593Smuzhiyun f = 0;
385*4882a593Smuzhiyun break;
386*4882a593Smuzhiyun case COMP_No_Comp:
387*4882a593Smuzhiyun f = X86_EFLAGS_ZF | X86_EFLAGS_PF | X86_EFLAGS_CF;
388*4882a593Smuzhiyun break;
389*4882a593Smuzhiyun #ifdef PARANOID
390*4882a593Smuzhiyun default:
391*4882a593Smuzhiyun EXCEPTION(EX_INTERNAL | 0x123);
392*4882a593Smuzhiyun f = 0;
393*4882a593Smuzhiyun break;
394*4882a593Smuzhiyun #endif /* PARANOID */
395*4882a593Smuzhiyun }
396*4882a593Smuzhiyun FPU_EFLAGS = (FPU_EFLAGS & ~(X86_EFLAGS_ZF | X86_EFLAGS_PF | X86_EFLAGS_CF)) | f;
397*4882a593Smuzhiyun if (c & COMP_Denormal) {
398*4882a593Smuzhiyun return denormal_operand() < 0;
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun return 0;
401*4882a593Smuzhiyun }
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun /*---------------------------------------------------------------------------*/
404*4882a593Smuzhiyun
fcom_st(void)405*4882a593Smuzhiyun void fcom_st(void)
406*4882a593Smuzhiyun {
407*4882a593Smuzhiyun /* fcom st(i) */
408*4882a593Smuzhiyun compare_st_st(FPU_rm);
409*4882a593Smuzhiyun }
410*4882a593Smuzhiyun
fcompst(void)411*4882a593Smuzhiyun void fcompst(void)
412*4882a593Smuzhiyun {
413*4882a593Smuzhiyun /* fcomp st(i) */
414*4882a593Smuzhiyun if (!compare_st_st(FPU_rm))
415*4882a593Smuzhiyun FPU_pop();
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun
fcompp(void)418*4882a593Smuzhiyun void fcompp(void)
419*4882a593Smuzhiyun {
420*4882a593Smuzhiyun /* fcompp */
421*4882a593Smuzhiyun if (FPU_rm != 1) {
422*4882a593Smuzhiyun FPU_illegal();
423*4882a593Smuzhiyun return;
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun if (!compare_st_st(1))
426*4882a593Smuzhiyun poppop();
427*4882a593Smuzhiyun }
428*4882a593Smuzhiyun
fucom_(void)429*4882a593Smuzhiyun void fucom_(void)
430*4882a593Smuzhiyun {
431*4882a593Smuzhiyun /* fucom st(i) */
432*4882a593Smuzhiyun compare_u_st_st(FPU_rm);
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun }
435*4882a593Smuzhiyun
fucomp(void)436*4882a593Smuzhiyun void fucomp(void)
437*4882a593Smuzhiyun {
438*4882a593Smuzhiyun /* fucomp st(i) */
439*4882a593Smuzhiyun if (!compare_u_st_st(FPU_rm))
440*4882a593Smuzhiyun FPU_pop();
441*4882a593Smuzhiyun }
442*4882a593Smuzhiyun
fucompp(void)443*4882a593Smuzhiyun void fucompp(void)
444*4882a593Smuzhiyun {
445*4882a593Smuzhiyun /* fucompp */
446*4882a593Smuzhiyun if (FPU_rm == 1) {
447*4882a593Smuzhiyun if (!compare_u_st_st(1))
448*4882a593Smuzhiyun poppop();
449*4882a593Smuzhiyun } else
450*4882a593Smuzhiyun FPU_illegal();
451*4882a593Smuzhiyun }
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun /* P6+ compare-to-EFLAGS ops */
454*4882a593Smuzhiyun
fcomi_(void)455*4882a593Smuzhiyun void fcomi_(void)
456*4882a593Smuzhiyun {
457*4882a593Smuzhiyun /* fcomi st(i) */
458*4882a593Smuzhiyun compare_i_st_st(FPU_rm);
459*4882a593Smuzhiyun }
460*4882a593Smuzhiyun
fcomip(void)461*4882a593Smuzhiyun void fcomip(void)
462*4882a593Smuzhiyun {
463*4882a593Smuzhiyun /* fcomip st(i) */
464*4882a593Smuzhiyun if (!compare_i_st_st(FPU_rm))
465*4882a593Smuzhiyun FPU_pop();
466*4882a593Smuzhiyun }
467*4882a593Smuzhiyun
fucomi_(void)468*4882a593Smuzhiyun void fucomi_(void)
469*4882a593Smuzhiyun {
470*4882a593Smuzhiyun /* fucomi st(i) */
471*4882a593Smuzhiyun compare_ui_st_st(FPU_rm);
472*4882a593Smuzhiyun }
473*4882a593Smuzhiyun
fucomip(void)474*4882a593Smuzhiyun void fucomip(void)
475*4882a593Smuzhiyun {
476*4882a593Smuzhiyun /* fucomip st(i) */
477*4882a593Smuzhiyun if (!compare_ui_st_st(FPU_rm))
478*4882a593Smuzhiyun FPU_pop();
479*4882a593Smuzhiyun }
480