dp_msubf.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /*
  2. * IEEE754 floating point arithmetic
  3. * double precision: MSUB.f (Fused Multiply Subtract)
  4. * MSUBF.fmt: FPR[fd] = FPR[fd] - (FPR[fs] x FPR[ft])
  5. *
  6. * MIPS floating point support
  7. * Copyright (C) 2015 Imagination Technologies, Ltd.
  8. * Author: Markos Chandras <markos.chandras@imgtec.com>
  9. *
  10. * This program is free software; you can distribute it and/or modify it
  11. * under the terms of the GNU General Public License as published by the
  12. * Free Software Foundation; version 2 of the License.
  13. */
  14. #include "ieee754dp.h"
  15. union ieee754dp ieee754dp_msubf(union ieee754dp z, union ieee754dp x,
  16. union ieee754dp y)
  17. {
  18. int re;
  19. int rs;
  20. u64 rm;
  21. unsigned lxm;
  22. unsigned hxm;
  23. unsigned lym;
  24. unsigned hym;
  25. u64 lrm;
  26. u64 hrm;
  27. u64 t;
  28. u64 at;
  29. int s;
  30. COMPXDP;
  31. COMPYDP;
  32. u64 zm; int ze; int zs __maybe_unused; int zc;
  33. EXPLODEXDP;
  34. EXPLODEYDP;
  35. EXPLODEDP(z, zc, zs, ze, zm)
  36. FLUSHXDP;
  37. FLUSHYDP;
  38. FLUSHDP(z, zc, zs, ze, zm);
  39. ieee754_clearcx();
  40. switch (zc) {
  41. case IEEE754_CLASS_SNAN:
  42. ieee754_setcx(IEEE754_INVALID_OPERATION);
  43. return ieee754dp_nanxcpt(z);
  44. case IEEE754_CLASS_DNORM:
  45. DPDNORMx(zm, ze);
  46. /* QNAN is handled separately below */
  47. }
  48. switch (CLPAIR(xc, yc)) {
  49. case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
  50. case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
  51. case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
  52. case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
  53. case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
  54. return ieee754dp_nanxcpt(y);
  55. case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
  56. case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
  57. case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
  58. case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
  59. case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
  60. case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
  61. return ieee754dp_nanxcpt(x);
  62. case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
  63. case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
  64. case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
  65. case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
  66. return y;
  67. case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
  68. case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
  69. case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
  70. case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
  71. case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
  72. return x;
  73. /*
  74. * Infinity handling
  75. */
  76. case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
  77. case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
  78. if (zc == IEEE754_CLASS_QNAN)
  79. return z;
  80. ieee754_setcx(IEEE754_INVALID_OPERATION);
  81. return ieee754dp_indef();
  82. case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
  83. case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
  84. case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
  85. case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
  86. case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
  87. if (zc == IEEE754_CLASS_QNAN)
  88. return z;
  89. return ieee754dp_inf(xs ^ ys);
  90. case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
  91. case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
  92. case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
  93. case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
  94. case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
  95. if (zc == IEEE754_CLASS_INF)
  96. return ieee754dp_inf(zs);
  97. /* Multiplication is 0 so just return z */
  98. return z;
  99. case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
  100. DPDNORMX;
  101. case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
  102. if (zc == IEEE754_CLASS_QNAN)
  103. return z;
  104. else if (zc == IEEE754_CLASS_INF)
  105. return ieee754dp_inf(zs);
  106. DPDNORMY;
  107. break;
  108. case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
  109. if (zc == IEEE754_CLASS_QNAN)
  110. return z;
  111. else if (zc == IEEE754_CLASS_INF)
  112. return ieee754dp_inf(zs);
  113. DPDNORMX;
  114. break;
  115. case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
  116. if (zc == IEEE754_CLASS_QNAN)
  117. return z;
  118. else if (zc == IEEE754_CLASS_INF)
  119. return ieee754dp_inf(zs);
  120. /* fall through to real computations */
  121. }
  122. /* Finally get to do some computation */
  123. /*
  124. * Do the multiplication bit first
  125. *
  126. * rm = xm * ym, re = xe + ye basically
  127. *
  128. * At this point xm and ym should have been normalized.
  129. */
  130. assert(xm & DP_HIDDEN_BIT);
  131. assert(ym & DP_HIDDEN_BIT);
  132. re = xe + ye;
  133. rs = xs ^ ys;
  134. /* shunt to top of word */
  135. xm <<= 64 - (DP_FBITS + 1);
  136. ym <<= 64 - (DP_FBITS + 1);
  137. /*
  138. * Multiply 32 bits xm, ym to give high 32 bits rm with stickness.
  139. */
  140. /* 32 * 32 => 64 */
  141. #define DPXMULT(x, y) ((u64)(x) * (u64)y)
  142. lxm = xm;
  143. hxm = xm >> 32;
  144. lym = ym;
  145. hym = ym >> 32;
  146. lrm = DPXMULT(lxm, lym);
  147. hrm = DPXMULT(hxm, hym);
  148. t = DPXMULT(lxm, hym);
  149. at = lrm + (t << 32);
  150. hrm += at < lrm;
  151. lrm = at;
  152. hrm = hrm + (t >> 32);
  153. t = DPXMULT(hxm, lym);
  154. at = lrm + (t << 32);
  155. hrm += at < lrm;
  156. lrm = at;
  157. hrm = hrm + (t >> 32);
  158. rm = hrm | (lrm != 0);
  159. /*
  160. * Sticky shift down to normal rounding precision.
  161. */
  162. if ((s64) rm < 0) {
  163. rm = (rm >> (64 - (DP_FBITS + 1 + 3))) |
  164. ((rm << (DP_FBITS + 1 + 3)) != 0);
  165. re++;
  166. } else {
  167. rm = (rm >> (64 - (DP_FBITS + 1 + 3 + 1))) |
  168. ((rm << (DP_FBITS + 1 + 3 + 1)) != 0);
  169. }
  170. assert(rm & (DP_HIDDEN_BIT << 3));
  171. /* And now the subtraction */
  172. /* flip sign of r and handle as add */
  173. rs ^= 1;
  174. assert(zm & DP_HIDDEN_BIT);
  175. /*
  176. * Provide guard,round and stick bit space.
  177. */
  178. zm <<= 3;
  179. if (ze > re) {
  180. /*
  181. * Have to shift y fraction right to align.
  182. */
  183. s = ze - re;
  184. rm = XDPSRS(rm, s);
  185. re += s;
  186. } else if (re > ze) {
  187. /*
  188. * Have to shift x fraction right to align.
  189. */
  190. s = re - ze;
  191. zm = XDPSRS(zm, s);
  192. ze += s;
  193. }
  194. assert(ze == re);
  195. assert(ze <= DP_EMAX);
  196. if (zs == rs) {
  197. /*
  198. * Generate 28 bit result of adding two 27 bit numbers
  199. * leaving result in xm, xs and xe.
  200. */
  201. zm = zm + rm;
  202. if (zm >> (DP_FBITS + 1 + 3)) { /* carry out */
  203. zm = XDPSRS1(zm);
  204. ze++;
  205. }
  206. } else {
  207. if (zm >= rm) {
  208. zm = zm - rm;
  209. } else {
  210. zm = rm - zm;
  211. zs = rs;
  212. }
  213. if (zm == 0)
  214. return ieee754dp_zero(ieee754_csr.rm == FPU_CSR_RD);
  215. /*
  216. * Normalize to rounding precision.
  217. */
  218. while ((zm >> (DP_FBITS + 3)) == 0) {
  219. zm <<= 1;
  220. ze--;
  221. }
  222. }
  223. return ieee754dp_format(zs, ze, zm);
  224. }