Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/powerpc/fpu/fpu_compare.c
39536 views
1
/* $NetBSD: fpu_compare.c,v 1.4 2005/12/11 12:18:42 christos Exp $ */
2
3
/*-
4
* SPDX-License-Identifier: BSD-3-Clause
5
*
6
* Copyright (c) 1992, 1993
7
* The Regents of the University of California. All rights reserved.
8
*
9
* This software was developed by the Computer Systems Engineering group
10
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
11
* contributed to Berkeley.
12
*
13
* All advertising materials mentioning features or use of this software
14
* must display the following acknowledgement:
15
* This product includes software developed by the University of
16
* California, Lawrence Berkeley Laboratory.
17
*
18
* Redistribution and use in source and binary forms, with or without
19
* modification, are permitted provided that the following conditions
20
* are met:
21
* 1. Redistributions of source code must retain the above copyright
22
* notice, this list of conditions and the following disclaimer.
23
* 2. Redistributions in binary form must reproduce the above copyright
24
* notice, this list of conditions and the following disclaimer in the
25
* documentation and/or other materials provided with the distribution.
26
* 3. Neither the name of the University nor the names of its contributors
27
* may be used to endorse or promote products derived from this software
28
* without specific prior written permission.
29
*
30
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
31
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
34
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40
* SUCH DAMAGE.
41
*/
42
43
/*
44
* FCMPU and FCMPO instructions.
45
*
46
* These rely on the fact that our internal wide format is achieved by
47
* adding zero bits to the end of narrower mantissas.
48
*/
49
50
#include <sys/types.h>
51
#include <sys/systm.h>
52
53
#include <machine/fpu.h>
54
55
#include <powerpc/fpu/fpu_arith.h>
56
#include <powerpc/fpu/fpu_emu.h>
57
58
/*
59
* Perform a compare instruction (with or without unordered exception).
60
* This updates the fcc field in the fsr.
61
*
62
* If either operand is NaN, the result is unordered. For ordered, this
63
* causes an NV exception. Everything else is ordered:
64
* |Inf| > |numbers| > |0|.
65
* We already arranged for fp_class(Inf) > fp_class(numbers) > fp_class(0),
66
* so we get this directly. Note, however, that two zeros compare equal
67
* regardless of sign, while everything else depends on sign.
68
*
69
* Incidentally, two Infs of the same sign compare equal (per the 80387
70
* manual---it would be nice if the SPARC documentation were more
71
* complete).
72
*/
73
void
74
fpu_compare(struct fpemu *fe, int ordered)
75
{
76
struct fpn *a, *b, *r;
77
int cc;
78
79
a = &fe->fe_f1;
80
b = &fe->fe_f2;
81
r = &fe->fe_f3;
82
83
if (ISNAN(a) || ISNAN(b)) {
84
/*
85
* In any case, we already got an exception for signalling
86
* NaNs; here we may replace that one with an identical
87
* exception, but so what?.
88
*/
89
cc = FPSCR_FU;
90
if (ISSNAN(a) || ISSNAN(b))
91
cc |= FPSCR_VXSNAN;
92
if (ordered) {
93
if (fe->fe_fpscr & FPSCR_VE || ISQNAN(a) || ISQNAN(b))
94
cc |= FPSCR_VXVC;
95
}
96
goto done;
97
}
98
99
/*
100
* Must handle both-zero early to avoid sign goofs. Otherwise,
101
* at most one is 0, and if the signs differ we are done.
102
*/
103
if (ISZERO(a) && ISZERO(b)) {
104
cc = FPSCR_FE;
105
goto done;
106
}
107
if (a->fp_sign) { /* a < 0 (or -0) */
108
if (!b->fp_sign) { /* b >= 0 (or if a = -0, b > 0) */
109
cc = FPSCR_FL;
110
goto done;
111
}
112
} else { /* a > 0 (or +0) */
113
if (b->fp_sign) { /* b <= -0 (or if a = +0, b < 0) */
114
cc = FPSCR_FG;
115
goto done;
116
}
117
}
118
119
/*
120
* Now the signs are the same (but may both be negative). All
121
* we have left are these cases:
122
*
123
* |a| < |b| [classes or values differ]
124
* |a| > |b| [classes or values differ]
125
* |a| == |b| [classes and values identical]
126
*
127
* We define `diff' here to expand these as:
128
*
129
* |a| < |b|, a,b >= 0: a < b => FSR_CC_LT
130
* |a| < |b|, a,b < 0: a > b => FSR_CC_GT
131
* |a| > |b|, a,b >= 0: a > b => FSR_CC_GT
132
* |a| > |b|, a,b < 0: a < b => FSR_CC_LT
133
*/
134
#define opposite_cc(cc) ((cc) == FPSCR_FL ? FPSCR_FG : FPSCR_FL)
135
#define diff(magnitude) (a->fp_sign ? opposite_cc(magnitude) : (magnitude))
136
if (a->fp_class < b->fp_class) { /* |a| < |b| */
137
cc = diff(FPSCR_FL);
138
goto done;
139
}
140
if (a->fp_class > b->fp_class) { /* |a| > |b| */
141
cc = diff(FPSCR_FG);
142
goto done;
143
}
144
/* now none can be 0: only Inf and numbers remain */
145
if (ISINF(a)) { /* |Inf| = |Inf| */
146
cc = FPSCR_FE;
147
goto done;
148
}
149
fpu_sub(fe);
150
if (ISZERO(r))
151
cc = FPSCR_FE;
152
else if (r->fp_sign)
153
cc = FPSCR_FL;
154
else
155
cc = FPSCR_FG;
156
done:
157
fe->fe_cx = cc;
158
}
159
160