vfpdouble.cpp 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432
  1. /*
  2. vfp/vfpdouble.c - ARM VFPv3 emulation unit - SoftFloat double instruction
  3. Copyright (C) 2003 Skyeye Develop Group
  4. for help please send mail to <skyeye-developer@lists.gro.clinux.org>
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  16. */
  17. /*
  18. * This code is derived in part from :
  19. * - Android kernel
  20. * - John R. Housers softfloat library, which
  21. * carries the following notice:
  22. *
  23. * ===========================================================================
  24. * This C source file is part of the SoftFloat IEC/IEEE Floating-point
  25. * Arithmetic Package, Release 2.
  26. *
  27. * Written by John R. Hauser. This work was made possible in part by the
  28. * International Computer Science Institute, located at Suite 600, 1947 Center
  29. * Street, Berkeley, California 94704. Funding was partially provided by the
  30. * National Science Foundation under grant MIP-9311980. The original version
  31. * of this code was written as part of a project to build a fixed-point vector
  32. * processor in collaboration with the University of California at Berkeley,
  33. * overseen by Profs. Nelson Morgan and John Wawrzynek. More information
  34. * is available through the web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
  35. * arithmetic/softfloat.html'.
  36. *
  37. * THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
  38. * has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
  39. * TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
  40. * PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
  41. * AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
  42. *
  43. * Derivative works are acceptable, even for commercial purposes, so long as
  44. * (1) they include prominent notice that the work is derivative, and (2) they
  45. * include prominent notice akin to these three paragraphs for those parts of
  46. * this code that are retained.
  47. * ===========================================================================
  48. */
  49. #include "core/arm/skyeye_common/vfp/vfp.h"
  50. #include "core/arm/skyeye_common/vfp/vfp_helper.h"
  51. #include "core/arm/skyeye_common/vfp/asm_vfp.h"
  52. static struct vfp_double vfp_double_default_qnan = {
  53. 2047,
  54. 0,
  55. VFP_DOUBLE_SIGNIFICAND_QNAN,
  56. };
  57. static void vfp_double_dump(const char *str, struct vfp_double *d)
  58. {
  59. pr_debug("VFP: %s: sign=%d exponent=%d significand=%016llx\n",
  60. str, d->sign != 0, d->exponent, d->significand);
  61. }
  62. static void vfp_double_normalise_denormal(struct vfp_double *vd)
  63. {
  64. int bits = 31 - fls((ARMword)(vd->significand >> 32));
  65. if (bits == 31)
  66. bits = 63 - fls((ARMword)vd->significand);
  67. vfp_double_dump("normalise_denormal: in", vd);
  68. if (bits) {
  69. vd->exponent -= bits - 1;
  70. vd->significand <<= bits;
  71. }
  72. vfp_double_dump("normalise_denormal: out", vd);
  73. }
  74. u32 vfp_double_normaliseroundintern(ARMul_State* state, struct vfp_double *vd, u32 fpscr, u32 exceptions, const char *func)
  75. {
  76. u64 significand, incr;
  77. int exponent, shift, underflow;
  78. u32 rmode;
  79. vfp_double_dump("pack: in", vd);
  80. /*
  81. * Infinities and NaNs are a special case.
  82. */
  83. if (vd->exponent == 2047 && (vd->significand == 0 || exceptions))
  84. goto pack;
  85. /*
  86. * Special-case zero.
  87. */
  88. if (vd->significand == 0) {
  89. vd->exponent = 0;
  90. goto pack;
  91. }
  92. exponent = vd->exponent;
  93. significand = vd->significand;
  94. shift = 32 - fls((ARMword)(significand >> 32));
  95. if (shift == 32)
  96. shift = 64 - fls((ARMword)significand);
  97. if (shift) {
  98. exponent -= shift;
  99. significand <<= shift;
  100. }
  101. #if 1
  102. vd->exponent = exponent;
  103. vd->significand = significand;
  104. vfp_double_dump("pack: normalised", vd);
  105. #endif
  106. /*
  107. * Tiny number?
  108. */
  109. underflow = exponent < 0;
  110. if (underflow) {
  111. significand = vfp_shiftright64jamming(significand, -exponent);
  112. exponent = 0;
  113. #if 1
  114. vd->exponent = exponent;
  115. vd->significand = significand;
  116. vfp_double_dump("pack: tiny number", vd);
  117. #endif
  118. if (!(significand & ((1ULL << (VFP_DOUBLE_LOW_BITS + 1)) - 1)))
  119. underflow = 0;
  120. }
  121. /*
  122. * Select rounding increment.
  123. */
  124. incr = 0;
  125. rmode = fpscr & FPSCR_RMODE_MASK;
  126. if (rmode == FPSCR_ROUND_NEAREST) {
  127. incr = 1ULL << VFP_DOUBLE_LOW_BITS;
  128. if ((significand & (1ULL << (VFP_DOUBLE_LOW_BITS + 1))) == 0)
  129. incr -= 1;
  130. }
  131. else if (rmode == FPSCR_ROUND_TOZERO) {
  132. incr = 0;
  133. }
  134. else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vd->sign != 0))
  135. incr = (1ULL << (VFP_DOUBLE_LOW_BITS + 1)) - 1;
  136. pr_debug("VFP: rounding increment = 0x%08llx\n", incr);
  137. /*
  138. * Is our rounding going to overflow?
  139. */
  140. if ((significand + incr) < significand) {
  141. exponent += 1;
  142. significand = (significand >> 1) | (significand & 1);
  143. incr >>= 1;
  144. #if 1
  145. vd->exponent = exponent;
  146. vd->significand = significand;
  147. vfp_double_dump("pack: overflow", vd);
  148. #endif
  149. }
  150. /*
  151. * If any of the low bits (which will be shifted out of the
  152. * number) are non-zero, the result is inexact.
  153. */
  154. if (significand & ((1 << (VFP_DOUBLE_LOW_BITS + 1)) - 1))
  155. exceptions |= FPSCR_IXC;
  156. /*
  157. * Do our rounding.
  158. */
  159. significand += incr;
  160. /*
  161. * Infinity?
  162. */
  163. if (exponent >= 2046) {
  164. exceptions |= FPSCR_OFC | FPSCR_IXC;
  165. if (incr == 0) {
  166. vd->exponent = 2045;
  167. vd->significand = 0x7fffffffffffffffULL;
  168. }
  169. else {
  170. vd->exponent = 2047; /* infinity */
  171. vd->significand = 0;
  172. }
  173. }
  174. else {
  175. if (significand >> (VFP_DOUBLE_LOW_BITS + 1) == 0)
  176. exponent = 0;
  177. if (exponent || significand > 0x8000000000000000ULL)
  178. underflow = 0;
  179. if (underflow)
  180. exceptions |= FPSCR_UFC;
  181. vd->exponent = exponent;
  182. vd->significand = significand >> 1;
  183. }
  184. pack:
  185. return 0;
  186. }
  187. u32 vfp_double_normaliseround(ARMul_State* state, int dd, struct vfp_double *vd, u32 fpscr, u32 exceptions, const char *func)
  188. {
  189. u64 significand, incr;
  190. int exponent, shift, underflow;
  191. u32 rmode;
  192. vfp_double_dump("pack: in", vd);
  193. /*
  194. * Infinities and NaNs are a special case.
  195. */
  196. if (vd->exponent == 2047 && (vd->significand == 0 || exceptions))
  197. goto pack;
  198. /*
  199. * Special-case zero.
  200. */
  201. if (vd->significand == 0) {
  202. vd->exponent = 0;
  203. goto pack;
  204. }
  205. exponent = vd->exponent;
  206. significand = vd->significand;
  207. shift = 32 - fls((ARMword)(significand >> 32));
  208. if (shift == 32)
  209. shift = 64 - fls((ARMword)significand);
  210. if (shift) {
  211. exponent -= shift;
  212. significand <<= shift;
  213. }
  214. #if 1
  215. vd->exponent = exponent;
  216. vd->significand = significand;
  217. vfp_double_dump("pack: normalised", vd);
  218. #endif
  219. /*
  220. * Tiny number?
  221. */
  222. underflow = exponent < 0;
  223. if (underflow) {
  224. significand = vfp_shiftright64jamming(significand, -exponent);
  225. exponent = 0;
  226. #if 1
  227. vd->exponent = exponent;
  228. vd->significand = significand;
  229. vfp_double_dump("pack: tiny number", vd);
  230. #endif
  231. if (!(significand & ((1ULL << (VFP_DOUBLE_LOW_BITS + 1)) - 1)))
  232. underflow = 0;
  233. }
  234. /*
  235. * Select rounding increment.
  236. */
  237. incr = 0;
  238. rmode = fpscr & FPSCR_RMODE_MASK;
  239. if (rmode == FPSCR_ROUND_NEAREST) {
  240. incr = 1ULL << VFP_DOUBLE_LOW_BITS;
  241. if ((significand & (1ULL << (VFP_DOUBLE_LOW_BITS + 1))) == 0)
  242. incr -= 1;
  243. } else if (rmode == FPSCR_ROUND_TOZERO) {
  244. incr = 0;
  245. } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vd->sign != 0))
  246. incr = (1ULL << (VFP_DOUBLE_LOW_BITS + 1)) - 1;
  247. pr_debug("VFP: rounding increment = 0x%08llx\n", incr);
  248. /*
  249. * Is our rounding going to overflow?
  250. */
  251. if ((significand + incr) < significand) {
  252. exponent += 1;
  253. significand = (significand >> 1) | (significand & 1);
  254. incr >>= 1;
  255. #if 1
  256. vd->exponent = exponent;
  257. vd->significand = significand;
  258. vfp_double_dump("pack: overflow", vd);
  259. #endif
  260. }
  261. /*
  262. * If any of the low bits (which will be shifted out of the
  263. * number) are non-zero, the result is inexact.
  264. */
  265. if (significand & ((1 << (VFP_DOUBLE_LOW_BITS + 1)) - 1))
  266. exceptions |= FPSCR_IXC;
  267. /*
  268. * Do our rounding.
  269. */
  270. significand += incr;
  271. /*
  272. * Infinity?
  273. */
  274. if (exponent >= 2046) {
  275. exceptions |= FPSCR_OFC | FPSCR_IXC;
  276. if (incr == 0) {
  277. vd->exponent = 2045;
  278. vd->significand = 0x7fffffffffffffffULL;
  279. } else {
  280. vd->exponent = 2047; /* infinity */
  281. vd->significand = 0;
  282. }
  283. } else {
  284. if (significand >> (VFP_DOUBLE_LOW_BITS + 1) == 0)
  285. exponent = 0;
  286. if (exponent || significand > 0x8000000000000000ULL)
  287. underflow = 0;
  288. if (underflow)
  289. exceptions |= FPSCR_UFC;
  290. vd->exponent = exponent;
  291. vd->significand = significand >> 1;
  292. }
  293. pack:
  294. vfp_double_dump("pack: final", vd);
  295. {
  296. s64 d = vfp_double_pack(vd);
  297. pr_debug("VFP: %s: d(d%d)=%016llx exceptions=%08x\n", func,
  298. dd, d, exceptions);
  299. vfp_put_double(state, d, dd);
  300. }
  301. return exceptions;
  302. }
  303. /*
  304. * Propagate the NaN, setting exceptions if it is signalling.
  305. * 'n' is always a NaN. 'm' may be a number, NaN or infinity.
  306. */
  307. static u32
  308. vfp_propagate_nan(struct vfp_double *vdd, struct vfp_double *vdn,
  309. struct vfp_double *vdm, u32 fpscr)
  310. {
  311. struct vfp_double *nan;
  312. int tn, tm = 0;
  313. tn = vfp_double_type(vdn);
  314. if (vdm)
  315. tm = vfp_double_type(vdm);
  316. if (fpscr & FPSCR_DEFAULT_NAN)
  317. /*
  318. * Default NaN mode - always returns a quiet NaN
  319. */
  320. nan = &vfp_double_default_qnan;
  321. else {
  322. /*
  323. * Contemporary mode - select the first signalling
  324. * NAN, or if neither are signalling, the first
  325. * quiet NAN.
  326. */
  327. if (tn == VFP_SNAN || (tm != VFP_SNAN && tn == VFP_QNAN))
  328. nan = vdn;
  329. else
  330. nan = vdm;
  331. /*
  332. * Make the NaN quiet.
  333. */
  334. nan->significand |= VFP_DOUBLE_SIGNIFICAND_QNAN;
  335. }
  336. *vdd = *nan;
  337. /*
  338. * If one was a signalling NAN, raise invalid operation.
  339. */
  340. return tn == VFP_SNAN || tm == VFP_SNAN ? FPSCR_IOC : VFP_NAN_FLAG;
  341. }
  342. /*
  343. * Extended operations
  344. */
  345. static u32 vfp_double_fabs(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
  346. {
  347. pr_debug("In %s\n", __FUNCTION__);
  348. vfp_put_double(state, vfp_double_packed_abs(vfp_get_double(state, dm)), dd);
  349. return 0;
  350. }
  351. static u32 vfp_double_fcpy(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
  352. {
  353. pr_debug("In %s\n", __FUNCTION__);
  354. vfp_put_double(state, vfp_get_double(state, dm), dd);
  355. return 0;
  356. }
  357. static u32 vfp_double_fneg(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
  358. {
  359. pr_debug("In %s\n", __FUNCTION__);
  360. vfp_put_double(state, vfp_double_packed_negate(vfp_get_double(state, dm)), dd);
  361. return 0;
  362. }
  363. static u32 vfp_double_fsqrt(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
  364. {
  365. pr_debug("In %s\n", __FUNCTION__);
  366. vfp_double vdm, vdd, *vdp;
  367. int ret, tm;
  368. vfp_double_unpack(&vdm, vfp_get_double(state, dm));
  369. tm = vfp_double_type(&vdm);
  370. if (tm & (VFP_NAN|VFP_INFINITY)) {
  371. vdp = &vdd;
  372. if (tm & VFP_NAN)
  373. ret = vfp_propagate_nan(vdp, &vdm, NULL, fpscr);
  374. else if (vdm.sign == 0) {
  375. sqrt_copy:
  376. vdp = &vdm;
  377. ret = 0;
  378. } else {
  379. sqrt_invalid:
  380. vdp = &vfp_double_default_qnan;
  381. ret = FPSCR_IOC;
  382. }
  383. vfp_put_double(state, vfp_double_pack(vdp), dd);
  384. return ret;
  385. }
  386. /*
  387. * sqrt(+/- 0) == +/- 0
  388. */
  389. if (tm & VFP_ZERO)
  390. goto sqrt_copy;
  391. /*
  392. * Normalise a denormalised number
  393. */
  394. if (tm & VFP_DENORMAL)
  395. vfp_double_normalise_denormal(&vdm);
  396. /*
  397. * sqrt(<0) = invalid
  398. */
  399. if (vdm.sign)
  400. goto sqrt_invalid;
  401. vfp_double_dump("sqrt", &vdm);
  402. /*
  403. * Estimate the square root.
  404. */
  405. vdd.sign = 0;
  406. vdd.exponent = ((vdm.exponent - 1023) >> 1) + 1023;
  407. vdd.significand = (u64)vfp_estimate_sqrt_significand(vdm.exponent, vdm.significand >> 32) << 31;
  408. vfp_double_dump("sqrt estimate1", &vdd);
  409. vdm.significand >>= 1 + (vdm.exponent & 1);
  410. vdd.significand += 2 + vfp_estimate_div128to64(vdm.significand, 0, vdd.significand);
  411. vfp_double_dump("sqrt estimate2", &vdd);
  412. /*
  413. * And now adjust.
  414. */
  415. if ((vdd.significand & VFP_DOUBLE_LOW_BITS_MASK) <= 5) {
  416. if (vdd.significand < 2) {
  417. vdd.significand = ~0ULL;
  418. } else {
  419. u64 termh, terml, remh, reml;
  420. vdm.significand <<= 2;
  421. mul64to128(&termh, &terml, vdd.significand, vdd.significand);
  422. sub128(&remh, &reml, vdm.significand, 0, termh, terml);
  423. while ((s64)remh < 0) {
  424. vdd.significand -= 1;
  425. shift64left(&termh, &terml, vdd.significand);
  426. terml |= 1;
  427. add128(&remh, &reml, remh, reml, termh, terml);
  428. }
  429. vdd.significand |= (remh | reml) != 0;
  430. }
  431. }
  432. vdd.significand = vfp_shiftright64jamming(vdd.significand, 1);
  433. return vfp_double_normaliseround(state, dd, &vdd, fpscr, 0, "fsqrt");
  434. }
  435. /*
  436. * Equal := ZC
  437. * Less than := N
  438. * Greater than := C
  439. * Unordered := CV
  440. */
  441. static u32 vfp_compare(ARMul_State* state, int dd, int signal_on_qnan, int dm, u32 fpscr)
  442. {
  443. s64 d, m;
  444. u32 ret = 0;
  445. pr_debug("In %s, state=0x%x, fpscr=0x%x\n", __FUNCTION__, state, fpscr);
  446. m = vfp_get_double(state, dm);
  447. if (vfp_double_packed_exponent(m) == 2047 && vfp_double_packed_mantissa(m)) {
  448. ret |= FPSCR_C | FPSCR_V;
  449. if (signal_on_qnan || !(vfp_double_packed_mantissa(m) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1))))
  450. /*
  451. * Signalling NaN, or signalling on quiet NaN
  452. */
  453. ret |= FPSCR_IOC;
  454. }
  455. d = vfp_get_double(state, dd);
  456. if (vfp_double_packed_exponent(d) == 2047 && vfp_double_packed_mantissa(d)) {
  457. ret |= FPSCR_C | FPSCR_V;
  458. if (signal_on_qnan || !(vfp_double_packed_mantissa(d) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1))))
  459. /*
  460. * Signalling NaN, or signalling on quiet NaN
  461. */
  462. ret |= FPSCR_IOC;
  463. }
  464. if (ret == 0) {
  465. //printf("In %s, d=%lld, m =%lld\n ", __FUNCTION__, d, m);
  466. if (d == m || vfp_double_packed_abs(d | m) == 0) {
  467. /*
  468. * equal
  469. */
  470. ret |= FPSCR_Z | FPSCR_C;
  471. //printf("In %s,1 ret=0x%x\n", __FUNCTION__, ret);
  472. } else if (vfp_double_packed_sign(d ^ m)) {
  473. /*
  474. * different signs
  475. */
  476. if (vfp_double_packed_sign(d))
  477. /*
  478. * d is negative, so d < m
  479. */
  480. ret |= FPSCR_N;
  481. else
  482. /*
  483. * d is positive, so d > m
  484. */
  485. ret |= FPSCR_C;
  486. } else if ((vfp_double_packed_sign(d) != 0) ^ (d < m)) {
  487. /*
  488. * d < m
  489. */
  490. ret |= FPSCR_N;
  491. } else if ((vfp_double_packed_sign(d) != 0) ^ (d > m)) {
  492. /*
  493. * d > m
  494. */
  495. ret |= FPSCR_C;
  496. }
  497. }
  498. pr_debug("In %s, state=0x%x, ret=0x%x\n", __FUNCTION__, state, ret);
  499. return ret;
  500. }
  501. static u32 vfp_double_fcmp(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
  502. {
  503. pr_debug("In %s\n", __FUNCTION__);
  504. return vfp_compare(state, dd, 0, dm, fpscr);
  505. }
  506. static u32 vfp_double_fcmpe(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
  507. {
  508. pr_debug("In %s\n", __FUNCTION__);
  509. return vfp_compare(state, dd, 1, dm, fpscr);
  510. }
  511. static u32 vfp_double_fcmpz(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
  512. {
  513. pr_debug("In %s\n", __FUNCTION__);
  514. return vfp_compare(state, dd, 0, VFP_REG_ZERO, fpscr);
  515. }
  516. static u32 vfp_double_fcmpez(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
  517. {
  518. pr_debug("In %s\n", __FUNCTION__);
  519. return vfp_compare(state, dd, 1, VFP_REG_ZERO, fpscr);
  520. }
  521. u32 vfp_double_fcvtsinterncutting(ARMul_State* state, int sd, struct vfp_double* dm, u32 fpscr) //ichfly for internal use only
  522. {
  523. struct vfp_single vsd;
  524. int tm;
  525. u32 exceptions = 0;
  526. pr_debug("In %s\n", __FUNCTION__);
  527. tm = vfp_double_type(dm);
  528. /*
  529. * If we have a signalling NaN, signal invalid operation.
  530. */
  531. if (tm == VFP_SNAN)
  532. exceptions = FPSCR_IOC;
  533. if (tm & VFP_DENORMAL)
  534. vfp_double_normalise_denormal(dm);
  535. vsd.sign = dm->sign;
  536. vsd.significand = vfp_hi64to32jamming(dm->significand);
  537. /*
  538. * If we have an infinity or a NaN, the exponent must be 255
  539. */
  540. if (tm & (VFP_INFINITY | VFP_NAN)) {
  541. vsd.exponent = 255;
  542. if (tm == VFP_QNAN)
  543. vsd.significand |= VFP_SINGLE_SIGNIFICAND_QNAN;
  544. goto pack_nan;
  545. }
  546. else if (tm & VFP_ZERO)
  547. vsd.exponent = 0;
  548. else
  549. vsd.exponent = dm->exponent - (1023 - 127);
  550. return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, "fcvts");
  551. pack_nan:
  552. vfp_put_float(state, vfp_single_pack(&vsd), sd);
  553. return exceptions;
  554. }
  555. static u32 vfp_double_fcvts(ARMul_State* state, int sd, int unused, int dm, u32 fpscr)
  556. {
  557. struct vfp_double vdm;
  558. struct vfp_single vsd;
  559. int tm;
  560. u32 exceptions = 0;
  561. pr_debug("In %s\n", __FUNCTION__);
  562. vfp_double_unpack(&vdm, vfp_get_double(state, dm));
  563. tm = vfp_double_type(&vdm);
  564. /*
  565. * If we have a signalling NaN, signal invalid operation.
  566. */
  567. if (tm == VFP_SNAN)
  568. exceptions = FPSCR_IOC;
  569. if (tm & VFP_DENORMAL)
  570. vfp_double_normalise_denormal(&vdm);
  571. vsd.sign = vdm.sign;
  572. vsd.significand = vfp_hi64to32jamming(vdm.significand);
  573. /*
  574. * If we have an infinity or a NaN, the exponent must be 255
  575. */
  576. if (tm & (VFP_INFINITY|VFP_NAN)) {
  577. vsd.exponent = 255;
  578. if (tm == VFP_QNAN)
  579. vsd.significand |= VFP_SINGLE_SIGNIFICAND_QNAN;
  580. goto pack_nan;
  581. } else if (tm & VFP_ZERO)
  582. vsd.exponent = 0;
  583. else
  584. vsd.exponent = vdm.exponent - (1023 - 127);
  585. return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, "fcvts");
  586. pack_nan:
  587. vfp_put_float(state, vfp_single_pack(&vsd), sd);
  588. return exceptions;
  589. }
  590. static u32 vfp_double_fuito(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
  591. {
  592. struct vfp_double vdm;
  593. u32 m = vfp_get_float(state, dm);
  594. pr_debug("In %s\n", __FUNCTION__);
  595. vdm.sign = 0;
  596. vdm.exponent = 1023 + 63 - 1;
  597. vdm.significand = (u64)m;
  598. return vfp_double_normaliseround(state, dd, &vdm, fpscr, 0, "fuito");
  599. }
  600. static u32 vfp_double_fsito(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
  601. {
  602. struct vfp_double vdm;
  603. u32 m = vfp_get_float(state, dm);
  604. pr_debug("In %s\n", __FUNCTION__);
  605. vdm.sign = (m & 0x80000000) >> 16;
  606. vdm.exponent = 1023 + 63 - 1;
  607. vdm.significand = vdm.sign ? -m : m;
  608. return vfp_double_normaliseround(state, dd, &vdm, fpscr, 0, "fsito");
  609. }
  610. static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32 fpscr)
  611. {
  612. struct vfp_double vdm;
  613. u32 d, exceptions = 0;
  614. int rmode = fpscr & FPSCR_RMODE_MASK;
  615. int tm;
  616. pr_debug("In %s\n", __FUNCTION__);
  617. vfp_double_unpack(&vdm, vfp_get_double(state, dm));
  618. /*
  619. * Do we have a denormalised number?
  620. */
  621. tm = vfp_double_type(&vdm);
  622. if (tm & VFP_DENORMAL)
  623. exceptions |= FPSCR_IDC;
  624. if (tm & VFP_NAN)
  625. vdm.sign = 0;
  626. if (vdm.exponent >= 1023 + 32) {
  627. d = vdm.sign ? 0 : 0xffffffff;
  628. exceptions = FPSCR_IOC;
  629. } else if (vdm.exponent >= 1023 - 1) {
  630. int shift = 1023 + 63 - vdm.exponent;
  631. u64 rem, incr = 0;
  632. /*
  633. * 2^0 <= m < 2^32-2^8
  634. */
  635. d = (ARMword)((vdm.significand << 1) >> shift);
  636. rem = vdm.significand << (65 - shift);
  637. if (rmode == FPSCR_ROUND_NEAREST) {
  638. incr = 0x8000000000000000ULL;
  639. if ((d & 1) == 0)
  640. incr -= 1;
  641. } else if (rmode == FPSCR_ROUND_TOZERO) {
  642. incr = 0;
  643. } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vdm.sign != 0)) {
  644. incr = ~0ULL;
  645. }
  646. if ((rem + incr) < rem) {
  647. if (d < 0xffffffff)
  648. d += 1;
  649. else
  650. exceptions |= FPSCR_IOC;
  651. }
  652. if (d && vdm.sign) {
  653. d = 0;
  654. exceptions |= FPSCR_IOC;
  655. } else if (rem)
  656. exceptions |= FPSCR_IXC;
  657. } else {
  658. d = 0;
  659. if (vdm.exponent | vdm.significand) {
  660. exceptions |= FPSCR_IXC;
  661. if (rmode == FPSCR_ROUND_PLUSINF && vdm.sign == 0)
  662. d = 1;
  663. else if (rmode == FPSCR_ROUND_MINUSINF && vdm.sign) {
  664. d = 0;
  665. exceptions |= FPSCR_IOC;
  666. }
  667. }
  668. }
  669. pr_debug("VFP: ftoui: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions);
  670. vfp_put_float(state, d, sd);
  671. return exceptions;
  672. }
  673. static u32 vfp_double_ftouiz(ARMul_State* state, int sd, int unused, int dm, u32 fpscr)
  674. {
  675. pr_debug("In %s\n", __FUNCTION__);
  676. return vfp_double_ftoui(state, sd, unused, dm, FPSCR_ROUND_TOZERO);
  677. }
  678. static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 fpscr)
  679. {
  680. struct vfp_double vdm;
  681. u32 d, exceptions = 0;
  682. int rmode = fpscr & FPSCR_RMODE_MASK;
  683. int tm;
  684. pr_debug("In %s\n", __FUNCTION__);
  685. vfp_double_unpack(&vdm, vfp_get_double(state, dm));
  686. vfp_double_dump("VDM", &vdm);
  687. /*
  688. * Do we have denormalised number?
  689. */
  690. tm = vfp_double_type(&vdm);
  691. if (tm & VFP_DENORMAL)
  692. exceptions |= FPSCR_IDC;
  693. if (tm & VFP_NAN) {
  694. d = 0;
  695. exceptions |= FPSCR_IOC;
  696. } else if (vdm.exponent >= 1023 + 32) {
  697. d = 0x7fffffff;
  698. if (vdm.sign)
  699. d = ~d;
  700. exceptions |= FPSCR_IOC;
  701. } else if (vdm.exponent >= 1023 - 1) {
  702. int shift = 1023 + 63 - vdm.exponent; /* 58 */
  703. u64 rem, incr = 0;
  704. d = (ARMword)((vdm.significand << 1) >> shift);
  705. rem = vdm.significand << (65 - shift);
  706. if (rmode == FPSCR_ROUND_NEAREST) {
  707. incr = 0x8000000000000000ULL;
  708. if ((d & 1) == 0)
  709. incr -= 1;
  710. } else if (rmode == FPSCR_ROUND_TOZERO) {
  711. incr = 0;
  712. } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vdm.sign != 0)) {
  713. incr = ~0ULL;
  714. }
  715. if ((rem + incr) < rem && d < 0xffffffff)
  716. d += 1;
  717. if (d > (0x7fffffff + (vdm.sign != 0))) {
  718. d = (0x7fffffff + (vdm.sign != 0));
  719. exceptions |= FPSCR_IOC;
  720. } else if (rem)
  721. exceptions |= FPSCR_IXC;
  722. if (vdm.sign)
  723. d = -d;
  724. } else {
  725. d = 0;
  726. if (vdm.exponent | vdm.significand) {
  727. exceptions |= FPSCR_IXC;
  728. if (rmode == FPSCR_ROUND_PLUSINF && vdm.sign == 0)
  729. d = 1;
  730. else if (rmode == FPSCR_ROUND_MINUSINF && vdm.sign)
  731. d = -1;
  732. }
  733. }
  734. pr_debug("VFP: ftosi: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions);
  735. vfp_put_float(state, (s32)d, sd);
  736. return exceptions;
  737. }
  738. static u32 vfp_double_ftosiz(ARMul_State* state, int dd, int unused, int dm, u32 fpscr)
  739. {
  740. pr_debug("In %s\n", __FUNCTION__);
  741. return vfp_double_ftosi(state, dd, unused, dm, FPSCR_ROUND_TOZERO);
  742. }
  743. static struct op fops_ext[] = {
  744. { vfp_double_fcpy, 0 }, //0x00000000 - FEXT_FCPY
  745. { vfp_double_fabs, 0 }, //0x00000001 - FEXT_FABS
  746. { vfp_double_fneg, 0 }, //0x00000002 - FEXT_FNEG
  747. { vfp_double_fsqrt, 0 }, //0x00000003 - FEXT_FSQRT
  748. { NULL, 0 },
  749. { NULL, 0 },
  750. { NULL, 0 },
  751. { NULL, 0 },
  752. { vfp_double_fcmp, OP_SCALAR }, //0x00000008 - FEXT_FCMP
  753. { vfp_double_fcmpe, OP_SCALAR }, //0x00000009 - FEXT_FCMPE
  754. { vfp_double_fcmpz, OP_SCALAR }, //0x0000000A - FEXT_FCMPZ
  755. { vfp_double_fcmpez, OP_SCALAR }, //0x0000000B - FEXT_FCMPEZ
  756. { NULL, 0 },
  757. { NULL, 0 },
  758. { NULL, 0 },
  759. { vfp_double_fcvts, OP_SCALAR|OP_DD }, //0x0000000F - FEXT_FCVT
  760. { vfp_double_fuito, OP_SCALAR }, //0x00000010 - FEXT_FUITO
  761. { vfp_double_fsito, OP_SCALAR }, //0x00000011 - FEXT_FSITO
  762. { NULL, 0 },
  763. { NULL, 0 },
  764. { NULL, 0 },
  765. { NULL, 0 },
  766. { NULL, 0 },
  767. { NULL, 0 },
  768. { vfp_double_ftoui, OP_SCALAR }, //0x00000018 - FEXT_FTOUI
  769. { vfp_double_ftouiz, OP_SCALAR }, //0x00000019 - FEXT_FTOUIZ
  770. { vfp_double_ftosi, OP_SCALAR }, //0x0000001A - FEXT_FTOSI
  771. { vfp_double_ftosiz, OP_SCALAR }, //0x0000001B - FEXT_FTOSIZ
  772. };
  773. static u32
  774. vfp_double_fadd_nonnumber(struct vfp_double *vdd, struct vfp_double *vdn,
  775. struct vfp_double *vdm, u32 fpscr)
  776. {
  777. struct vfp_double *vdp;
  778. u32 exceptions = 0;
  779. int tn, tm;
  780. tn = vfp_double_type(vdn);
  781. tm = vfp_double_type(vdm);
  782. if (tn & tm & VFP_INFINITY) {
  783. /*
  784. * Two infinities. Are they different signs?
  785. */
  786. if (vdn->sign ^ vdm->sign) {
  787. /*
  788. * different signs -> invalid
  789. */
  790. exceptions = FPSCR_IOC;
  791. vdp = &vfp_double_default_qnan;
  792. } else {
  793. /*
  794. * same signs -> valid
  795. */
  796. vdp = vdn;
  797. }
  798. } else if (tn & VFP_INFINITY && tm & VFP_NUMBER) {
  799. /*
  800. * One infinity and one number -> infinity
  801. */
  802. vdp = vdn;
  803. } else {
  804. /*
  805. * 'n' is a NaN of some type
  806. */
  807. return vfp_propagate_nan(vdd, vdn, vdm, fpscr);
  808. }
  809. *vdd = *vdp;
  810. return exceptions;
  811. }
  812. u32 vfp_double_add(struct vfp_double *vdd, struct vfp_double *vdn,struct vfp_double *vdm, u32 fpscr)
  813. {
  814. u32 exp_diff;
  815. u64 m_sig;
  816. if (vdn->significand & (1ULL << 63) ||
  817. vdm->significand & (1ULL << 63)) {
  818. pr_info("VFP: bad FP values in %s\n", __func__);
  819. vfp_double_dump("VDN", vdn);
  820. vfp_double_dump("VDM", vdm);
  821. }
  822. /*
  823. * Ensure that 'n' is the largest magnitude number. Note that
  824. * if 'n' and 'm' have equal exponents, we do not swap them.
  825. * This ensures that NaN propagation works correctly.
  826. */
  827. if (vdn->exponent < vdm->exponent) {
  828. struct vfp_double *t = vdn;
  829. vdn = vdm;
  830. vdm = t;
  831. }
  832. /*
  833. * Is 'n' an infinity or a NaN? Note that 'm' may be a number,
  834. * infinity or a NaN here.
  835. */
  836. if (vdn->exponent == 2047)
  837. return vfp_double_fadd_nonnumber(vdd, vdn, vdm, fpscr);
  838. /*
  839. * We have two proper numbers, where 'vdn' is the larger magnitude.
  840. *
  841. * Copy 'n' to 'd' before doing the arithmetic.
  842. */
  843. *vdd = *vdn;
  844. /*
  845. * Align 'm' with the result.
  846. */
  847. exp_diff = vdn->exponent - vdm->exponent;
  848. m_sig = vfp_shiftright64jamming(vdm->significand, exp_diff);
  849. /*
  850. * If the signs are different, we are really subtracting.
  851. */
  852. if (vdn->sign ^ vdm->sign) {
  853. m_sig = vdn->significand - m_sig;
  854. if ((s64)m_sig < 0) {
  855. vdd->sign = vfp_sign_negate(vdd->sign);
  856. m_sig = -m_sig;
  857. } else if (m_sig == 0) {
  858. vdd->sign = (fpscr & FPSCR_RMODE_MASK) ==
  859. FPSCR_ROUND_MINUSINF ? 0x8000 : 0;
  860. }
  861. } else {
  862. m_sig += vdn->significand;
  863. }
  864. vdd->significand = m_sig;
  865. return 0;
  866. }
  867. u32
  868. vfp_double_multiply(struct vfp_double *vdd, struct vfp_double *vdn,
  869. struct vfp_double *vdm, u32 fpscr)
  870. {
  871. vfp_double_dump("VDN", vdn);
  872. vfp_double_dump("VDM", vdm);
  873. /*
  874. * Ensure that 'n' is the largest magnitude number. Note that
  875. * if 'n' and 'm' have equal exponents, we do not swap them.
  876. * This ensures that NaN propagation works correctly.
  877. */
  878. if (vdn->exponent < vdm->exponent) {
  879. struct vfp_double *t = vdn;
  880. vdn = vdm;
  881. vdm = t;
  882. pr_debug("VFP: swapping M <-> N\n");
  883. }
  884. vdd->sign = vdn->sign ^ vdm->sign;
  885. /*
  886. * If 'n' is an infinity or NaN, handle it. 'm' may be anything.
  887. */
  888. if (vdn->exponent == 2047) {
  889. if (vdn->significand || (vdm->exponent == 2047 && vdm->significand))
  890. return vfp_propagate_nan(vdd, vdn, vdm, fpscr);
  891. if ((vdm->exponent | vdm->significand) == 0) {
  892. *vdd = vfp_double_default_qnan;
  893. return FPSCR_IOC;
  894. }
  895. vdd->exponent = vdn->exponent;
  896. vdd->significand = 0;
  897. return 0;
  898. }
  899. /*
  900. * If 'm' is zero, the result is always zero. In this case,
  901. * 'n' may be zero or a number, but it doesn't matter which.
  902. */
  903. if ((vdm->exponent | vdm->significand) == 0) {
  904. vdd->exponent = 0;
  905. vdd->significand = 0;
  906. return 0;
  907. }
  908. /*
  909. * We add 2 to the destination exponent for the same reason
  910. * as the addition case - though this time we have +1 from
  911. * each input operand.
  912. */
  913. vdd->exponent = vdn->exponent + vdm->exponent - 1023 + 2;
  914. vdd->significand = vfp_hi64multiply64(vdn->significand, vdm->significand);
  915. vfp_double_dump("VDD", vdd);
  916. return 0;
  917. }
  918. #define NEG_MULTIPLY (1 << 0)
  919. #define NEG_SUBTRACT (1 << 1)
  920. static u32
  921. vfp_double_multiply_accumulate(ARMul_State* state, int dd, int dn, int dm, u32 fpscr, u32 negate, const char *func)
  922. {
  923. struct vfp_double vdd, vdp, vdn, vdm;
  924. u32 exceptions;
  925. vfp_double_unpack(&vdn, vfp_get_double(state, dn));
  926. if (vdn.exponent == 0 && vdn.significand)
  927. vfp_double_normalise_denormal(&vdn);
  928. vfp_double_unpack(&vdm, vfp_get_double(state, dm));
  929. if (vdm.exponent == 0 && vdm.significand)
  930. vfp_double_normalise_denormal(&vdm);
  931. exceptions = vfp_double_multiply(&vdp, &vdn, &vdm, fpscr);
  932. if (negate & NEG_MULTIPLY)
  933. vdp.sign = vfp_sign_negate(vdp.sign);
  934. vfp_double_unpack(&vdn, vfp_get_double(state, dd));
  935. if (negate & NEG_SUBTRACT)
  936. vdn.sign = vfp_sign_negate(vdn.sign);
  937. exceptions |= vfp_double_add(&vdd, &vdn, &vdp, fpscr);
  938. return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, func);
  939. }
  940. /*
  941. * Standard operations
  942. */
  943. /*
  944. * sd = sd + (sn * sm)
  945. */
  946. static u32 vfp_double_fmac(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
  947. {
  948. pr_debug("In %s\n", __FUNCTION__);
  949. return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, 0, "fmac");
  950. }
  951. /*
  952. * sd = sd - (sn * sm)
  953. */
  954. static u32 vfp_double_fnmac(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
  955. {
  956. pr_debug("In %s\n", __FUNCTION__);
  957. return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_MULTIPLY, "fnmac");
  958. }
  959. /*
  960. * sd = -sd + (sn * sm)
  961. */
  962. static u32 vfp_double_fmsc(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
  963. {
  964. pr_debug("In %s\n", __FUNCTION__);
  965. return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_SUBTRACT, "fmsc");
  966. }
  967. /*
  968. * sd = -sd - (sn * sm)
  969. */
  970. static u32 vfp_double_fnmsc(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
  971. {
  972. pr_debug("In %s\n", __FUNCTION__);
  973. return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_SUBTRACT | NEG_MULTIPLY, "fnmsc");
  974. }
  975. /*
  976. * sd = sn * sm
  977. */
  978. static u32 vfp_double_fmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
  979. {
  980. struct vfp_double vdd, vdn, vdm;
  981. u32 exceptions;
  982. pr_debug("In %s\n", __FUNCTION__);
  983. vfp_double_unpack(&vdn, vfp_get_double(state, dn));
  984. if (vdn.exponent == 0 && vdn.significand)
  985. vfp_double_normalise_denormal(&vdn);
  986. vfp_double_unpack(&vdm, vfp_get_double(state, dm));
  987. if (vdm.exponent == 0 && vdm.significand)
  988. vfp_double_normalise_denormal(&vdm);
  989. exceptions = vfp_double_multiply(&vdd, &vdn, &vdm, fpscr);
  990. return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fmul");
  991. }
  992. /*
  993. * sd = -(sn * sm)
  994. */
  995. static u32 vfp_double_fnmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
  996. {
  997. struct vfp_double vdd, vdn, vdm;
  998. u32 exceptions;
  999. pr_debug("In %s\n", __FUNCTION__);
  1000. vfp_double_unpack(&vdn, vfp_get_double(state, dn));
  1001. if (vdn.exponent == 0 && vdn.significand)
  1002. vfp_double_normalise_denormal(&vdn);
  1003. vfp_double_unpack(&vdm, vfp_get_double(state, dm));
  1004. if (vdm.exponent == 0 && vdm.significand)
  1005. vfp_double_normalise_denormal(&vdm);
  1006. exceptions = vfp_double_multiply(&vdd, &vdn, &vdm, fpscr);
  1007. vdd.sign = vfp_sign_negate(vdd.sign);
  1008. return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fnmul");
  1009. }
  1010. /*
  1011. * sd = sn + sm
  1012. */
  1013. static u32 vfp_double_fadd(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
  1014. {
  1015. struct vfp_double vdd, vdn, vdm;
  1016. u32 exceptions;
  1017. pr_debug("In %s\n", __FUNCTION__);
  1018. vfp_double_unpack(&vdn, vfp_get_double(state, dn));
  1019. if (vdn.exponent == 0 && vdn.significand)
  1020. vfp_double_normalise_denormal(&vdn);
  1021. vfp_double_unpack(&vdm, vfp_get_double(state, dm));
  1022. if (vdm.exponent == 0 && vdm.significand)
  1023. vfp_double_normalise_denormal(&vdm);
  1024. exceptions = vfp_double_add(&vdd, &vdn, &vdm, fpscr);
  1025. return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fadd");
  1026. }
  1027. /*
  1028. * sd = sn - sm
  1029. */
  1030. static u32 vfp_double_fsub(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
  1031. {
  1032. struct vfp_double vdd, vdn, vdm;
  1033. u32 exceptions;
  1034. pr_debug("In %s\n", __FUNCTION__);
  1035. vfp_double_unpack(&vdn, vfp_get_double(state, dn));
  1036. if (vdn.exponent == 0 && vdn.significand)
  1037. vfp_double_normalise_denormal(&vdn);
  1038. vfp_double_unpack(&vdm, vfp_get_double(state, dm));
  1039. if (vdm.exponent == 0 && vdm.significand)
  1040. vfp_double_normalise_denormal(&vdm);
  1041. /*
  1042. * Subtraction is like addition, but with a negated operand.
  1043. */
  1044. vdm.sign = vfp_sign_negate(vdm.sign);
  1045. exceptions = vfp_double_add(&vdd, &vdn, &vdm, fpscr);
  1046. return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fsub");
  1047. }
  1048. /*
  1049. * sd = sn / sm
  1050. */
  1051. static u32 vfp_double_fdiv(ARMul_State* state, int dd, int dn, int dm, u32 fpscr)
  1052. {
  1053. struct vfp_double vdd, vdn, vdm;
  1054. u32 exceptions = 0;
  1055. int tm, tn;
  1056. pr_debug("In %s\n", __FUNCTION__);
  1057. vfp_double_unpack(&vdn, vfp_get_double(state, dn));
  1058. vfp_double_unpack(&vdm, vfp_get_double(state, dm));
  1059. vdd.sign = vdn.sign ^ vdm.sign;
  1060. tn = vfp_double_type(&vdn);
  1061. tm = vfp_double_type(&vdm);
  1062. /*
  1063. * Is n a NAN?
  1064. */
  1065. if (tn & VFP_NAN)
  1066. goto vdn_nan;
  1067. /*
  1068. * Is m a NAN?
  1069. */
  1070. if (tm & VFP_NAN)
  1071. goto vdm_nan;
  1072. /*
  1073. * If n and m are infinity, the result is invalid
  1074. * If n and m are zero, the result is invalid
  1075. */
  1076. if (tm & tn & (VFP_INFINITY|VFP_ZERO))
  1077. goto invalid;
  1078. /*
  1079. * If n is infinity, the result is infinity
  1080. */
  1081. if (tn & VFP_INFINITY)
  1082. goto infinity;
  1083. /*
  1084. * If m is zero, raise div0 exceptions
  1085. */
  1086. if (tm & VFP_ZERO)
  1087. goto divzero;
  1088. /*
  1089. * If m is infinity, or n is zero, the result is zero
  1090. */
  1091. if (tm & VFP_INFINITY || tn & VFP_ZERO)
  1092. goto zero;
  1093. if (tn & VFP_DENORMAL)
  1094. vfp_double_normalise_denormal(&vdn);
  1095. if (tm & VFP_DENORMAL)
  1096. vfp_double_normalise_denormal(&vdm);
  1097. /*
  1098. * Ok, we have two numbers, we can perform division.
  1099. */
  1100. vdd.exponent = vdn.exponent - vdm.exponent + 1023 - 1;
  1101. vdm.significand <<= 1;
  1102. if (vdm.significand <= (2 * vdn.significand)) {
  1103. vdn.significand >>= 1;
  1104. vdd.exponent++;
  1105. }
  1106. vdd.significand = vfp_estimate_div128to64(vdn.significand, 0, vdm.significand);
  1107. if ((vdd.significand & 0x1ff) <= 2) {
  1108. u64 termh, terml, remh, reml;
  1109. mul64to128(&termh, &terml, vdm.significand, vdd.significand);
  1110. sub128(&remh, &reml, vdn.significand, 0, termh, terml);
  1111. while ((s64)remh < 0) {
  1112. vdd.significand -= 1;
  1113. add128(&remh, &reml, remh, reml, 0, vdm.significand);
  1114. }
  1115. vdd.significand |= (reml != 0);
  1116. }
  1117. return vfp_double_normaliseround(state, dd, &vdd, fpscr, 0, "fdiv");
  1118. vdn_nan:
  1119. exceptions = vfp_propagate_nan(&vdd, &vdn, &vdm, fpscr);
  1120. pack:
  1121. vfp_put_double(state, vfp_double_pack(&vdd), dd);
  1122. return exceptions;
  1123. vdm_nan:
  1124. exceptions = vfp_propagate_nan(&vdd, &vdm, &vdn, fpscr);
  1125. goto pack;
  1126. zero:
  1127. vdd.exponent = 0;
  1128. vdd.significand = 0;
  1129. goto pack;
  1130. divzero:
  1131. exceptions = FPSCR_DZC;
  1132. infinity:
  1133. vdd.exponent = 2047;
  1134. vdd.significand = 0;
  1135. goto pack;
  1136. invalid:
  1137. vfp_put_double(state, vfp_double_pack(&vfp_double_default_qnan), dd);
  1138. return FPSCR_IOC;
  1139. }
  1140. static struct op fops[] = {
  1141. { vfp_double_fmac, 0 },
  1142. { vfp_double_fmsc, 0 },
  1143. { vfp_double_fmul, 0 },
  1144. { vfp_double_fadd, 0 },
  1145. { vfp_double_fnmac, 0 },
  1146. { vfp_double_fnmsc, 0 },
  1147. { vfp_double_fnmul, 0 },
  1148. { vfp_double_fsub, 0 },
  1149. { vfp_double_fdiv, 0 },
  1150. };
  1151. #define FREG_BANK(x) ((x) & 0x0c)
  1152. #define FREG_IDX(x) ((x) & 3)
  1153. u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr)
  1154. {
  1155. u32 op = inst & FOP_MASK;
  1156. u32 exceptions = 0;
  1157. unsigned int dest;
  1158. unsigned int dn = vfp_get_dn(inst);
  1159. unsigned int dm;
  1160. unsigned int vecitr, veclen, vecstride;
  1161. struct op *fop;
  1162. pr_debug("In %s\n", __FUNCTION__);
  1163. vecstride = (1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK));
  1164. fop = (op == FOP_EXT) ? &fops_ext[FEXT_TO_IDX(inst)] : &fops[FOP_TO_IDX(op)];
  1165. /*
  1166. * fcvtds takes an sN register number as destination, not dN.
  1167. * It also always operates on scalars.
  1168. */
  1169. if (fop->flags & OP_SD)
  1170. dest = vfp_get_sd(inst);
  1171. else
  1172. dest = vfp_get_dd(inst);
  1173. /*
  1174. * f[us]ito takes a sN operand, not a dN operand.
  1175. */
  1176. if (fop->flags & OP_SM)
  1177. dm = vfp_get_sm(inst);
  1178. else
  1179. dm = vfp_get_dm(inst);
  1180. /*
  1181. * If destination bank is zero, vector length is always '1'.
  1182. * ARM DDI0100F C5.1.3, C5.3.2.
  1183. */
  1184. if ((fop->flags & OP_SCALAR) || (FREG_BANK(dest) == 0))
  1185. veclen = 0;
  1186. else
  1187. veclen = fpscr & FPSCR_LENGTH_MASK;
  1188. pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride,
  1189. (veclen >> FPSCR_LENGTH_BIT) + 1);
  1190. if (!fop->fn) {
  1191. printf("VFP: could not find double op %d\n", FEXT_TO_IDX(inst));
  1192. goto invalid;
  1193. }
  1194. for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) {
  1195. u32 except;
  1196. char type;
  1197. type = (fop->flags & OP_SD) ? 's' : 'd';
  1198. if (op == FOP_EXT)
  1199. pr_debug("VFP: itr%d (%c%u) = op[%u] (d%u)\n",
  1200. vecitr >> FPSCR_LENGTH_BIT,
  1201. type, dest, dn, dm);
  1202. else
  1203. pr_debug("VFP: itr%d (%c%u) = (d%u) op[%u] (d%u)\n",
  1204. vecitr >> FPSCR_LENGTH_BIT,
  1205. type, dest, dn, FOP_TO_IDX(op), dm);
  1206. except = fop->fn(state, dest, dn, dm, fpscr);
  1207. pr_debug("VFP: itr%d: exceptions=%08x\n",
  1208. vecitr >> FPSCR_LENGTH_BIT, except);
  1209. exceptions |= except;
  1210. /*
  1211. * CHECK: It appears to be undefined whether we stop when
  1212. * we encounter an exception. We continue.
  1213. */
  1214. dest = FREG_BANK(dest) + ((FREG_IDX(dest) + vecstride) & 3);
  1215. dn = FREG_BANK(dn) + ((FREG_IDX(dn) + vecstride) & 3);
  1216. if (FREG_BANK(dm) != 0)
  1217. dm = FREG_BANK(dm) + ((FREG_IDX(dm) + vecstride) & 3);
  1218. }
  1219. return exceptions;
  1220. invalid:
  1221. return ~0;
  1222. }