fpu_compare.c 5.0 KB

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