float.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include <mach.h>
  5. #define Extern extern
  6. #include "power.h"
  7. ulong setfpscr(void);
  8. void setfpcc(double);
  9. void farith(ulong);
  10. void farith2(ulong);
  11. void fariths(ulong);
  12. void fcmp(ulong);
  13. void mtfsb1(ulong);
  14. void mcrfs(ulong);
  15. void mtfsb0(ulong);
  16. void mtfsf(ulong);
  17. void mtfsfi(ulong);
  18. void mffs(ulong);
  19. void mtfsf(ulong);
  20. Inst op59[] = {
  21. [18] {fariths, "fdivs", Ifloat},
  22. [20] {fariths, "fsubs", Ifloat},
  23. [21] {fariths, "fadds", Ifloat},
  24. [22] {unimp, "fsqrts", Ifloat},
  25. [24] {unimp, "fres", Ifloat},
  26. [25] {fariths, "fmuls", Ifloat},
  27. [28] {fariths, "fmsubs", Ifloat},
  28. [29] {fariths, "fmadds", Ifloat},
  29. [30] {fariths, "fnmsubs", Ifloat},
  30. [31] {fariths, "fnmadds", Ifloat},
  31. };
  32. Inset ops59 = {op59, nelem(op59)};
  33. Inst op63a[] = {
  34. [12] {farith, "frsp", Ifloat},
  35. [14] {farith, "fctiw", Ifloat},
  36. [15] {farith, "fctiwz", Ifloat},
  37. [18] {farith, "fdiv", Ifloat},
  38. [20] {farith, "fsub", Ifloat},
  39. [21] {farith, "fadd", Ifloat},
  40. [22] {unimp, "frsqrt", Ifloat},
  41. [23] {unimp, "fsel", Ifloat},
  42. [25] {farith, "fmul", Ifloat},
  43. [26] {unimp, "frsqrte", Ifloat},
  44. [28] {farith, "fmsub", Ifloat},
  45. [29] {farith, "fmadd", Ifloat},
  46. [30] {farith, "fnmsub", Ifloat},
  47. [31] {farith, "fnmadd", Ifloat},
  48. };
  49. Inset ops63a= {op63a, nelem(op63a)};
  50. Inst op63b[] = {
  51. [0] {fcmp, "fcmpu", Ifloat},
  52. [32] {fcmp, "fcmpo", Ifloat},
  53. [38] {mtfsb1, "mtfsb1", Ifloat},
  54. [40] {farith2, "fneg", Ifloat},
  55. [64] {mcrfs, "mcrfs", Ifloat},
  56. [70] {mtfsb0, "mtfsb0", Ifloat},
  57. [72] {farith2, "fmr", Ifloat},
  58. [134] {mtfsfi, "mtfsfi", Ifloat},
  59. [136] {farith2, "fnabs", Ifloat},
  60. [264] {farith2, "fabs", Ifloat},
  61. [583] {mffs, "mffs", Ifloat},
  62. [711] {mtfsf, "mtfsf", Ifloat},
  63. };
  64. Inset ops63b = {op63b, nelem(op63b)};
  65. void
  66. lfs(ulong ir)
  67. {
  68. ulong ea;
  69. int imm, ra, rd, upd;
  70. union {
  71. ulong i;
  72. float f;
  73. } u;
  74. getairr(ir);
  75. ea = imm;
  76. upd = (ir&(1L<<26))!=0;
  77. if(ra) {
  78. ea += reg.r[ra];
  79. if(upd)
  80. reg.r[ra] = ea;
  81. } else {
  82. if(upd)
  83. undef(ir);
  84. }
  85. if(trace)
  86. itrace("%s\tf%d,%ld(r%d) ea=%lux", ci->name, rd, imm, ra, ea);
  87. u.i = getmem_w(ea);
  88. reg.fd[rd] = u.f;
  89. }
  90. void
  91. lfsx(ulong ir)
  92. {
  93. ulong ea;
  94. int rd, ra, rb, upd;
  95. union {
  96. ulong i;
  97. float f;
  98. } u;
  99. getarrr(ir);
  100. ea = reg.r[rb];
  101. upd = ((ir>>1)&0x3FF)==567;
  102. if(ra){
  103. ea += reg.r[ra];
  104. if(upd)
  105. reg.r[ra] = ea;
  106. if(trace)
  107. itrace("%s\tf%d,(r%d+r%d) ea=%lux", ci->name, rd, ra, rb, ea);
  108. } else {
  109. if(upd)
  110. undef(ir);
  111. if(trace)
  112. itrace("%s\tf%d,(r%d) ea=%lux", ci->name, rd, rb, ea);
  113. }
  114. u.i = getmem_w(ea);
  115. reg.fd[rd] = u.f;
  116. }
  117. void
  118. lfd(ulong ir)
  119. {
  120. ulong ea;
  121. int imm, ra, rd, upd;
  122. getairr(ir);
  123. ea = imm;
  124. upd = (ir&(1L<<26))!=0;
  125. if(ra) {
  126. ea += reg.r[ra];
  127. if(upd)
  128. reg.r[ra] = ea;
  129. } else {
  130. if(upd)
  131. undef(ir);
  132. }
  133. if(trace)
  134. itrace("%s\tf%d,%ld(r%d) ea=%lux", ci->name, rd, imm, ra, ea);
  135. reg.dv[rd] = getmem_v(ea);
  136. }
  137. void
  138. lfdx(ulong ir)
  139. {
  140. ulong ea;
  141. int rd, ra, rb, upd;
  142. getarrr(ir);
  143. ea = reg.r[rb];
  144. upd = ((ir>>1)&0x3FF)==631;
  145. if(ra){
  146. ea += reg.r[ra];
  147. if(upd)
  148. reg.r[ra] = ea;
  149. if(trace)
  150. itrace("%s\tf%d,(r%d+r%d) ea=%lux", ci->name, rd, ra, rb, ea);
  151. } else {
  152. if(upd)
  153. undef(ir);
  154. if(trace)
  155. itrace("%s\tf%d,(r%d) ea=%lux", ci->name, rd, rb, ea);
  156. }
  157. reg.dv[rd] = getmem_v(ea);
  158. }
  159. void
  160. stfs(ulong ir)
  161. {
  162. ulong ea;
  163. int imm, ra, rd, upd;
  164. union {
  165. float f;
  166. ulong w;
  167. } u;
  168. getairr(ir);
  169. ea = imm;
  170. upd = (ir&(1L<<26))!=0;
  171. if(ra) {
  172. ea += reg.r[ra];
  173. if(upd)
  174. reg.r[ra] = ea;
  175. } else {
  176. if(upd)
  177. undef(ir);
  178. }
  179. if(trace)
  180. itrace("%s\tf%d,%ld(r%d) %lux=%g",
  181. ci->name, rd, imm, ra, ea, reg.fd[rd]);
  182. u.f = reg.fd[rd]; /* BUG: actual PPC conversion is more subtle than this */
  183. putmem_w(ea, u.w);
  184. }
  185. void
  186. stfsx(ulong ir)
  187. {
  188. ulong ea;
  189. int rd, ra, rb, upd;
  190. union {
  191. float f;
  192. ulong w;
  193. } u;
  194. getarrr(ir);
  195. ea = reg.r[rb];
  196. upd = getxo(ir)==695;
  197. if(ra){
  198. ea += reg.r[ra];
  199. if(upd)
  200. reg.r[ra] = ea;
  201. if(trace)
  202. itrace("%s\tf%d,(r%d+r%d) %lux=%g", ci->name, rd, ra, rb, ea, (float)reg.fd[rd]);
  203. } else {
  204. if(upd)
  205. undef(ir);
  206. if(trace)
  207. itrace("%s\tf%d,(r%d) %lux=%g", ci->name, rd, rb, ea, (float)reg.fd[rd]);
  208. }
  209. u.f = reg.fd[rd]; /* BUG: actual PPC conversion is more subtle than this */
  210. putmem_w(ea, u.w);
  211. }
  212. void
  213. stfd(ulong ir)
  214. {
  215. ulong ea;
  216. int imm, ra, rd, upd;
  217. getairr(ir);
  218. ea = imm;
  219. upd = (ir&(1L<<26))!=0;
  220. if(ra) {
  221. ea += reg.r[ra];
  222. if(upd)
  223. reg.r[ra] = ea;
  224. } else {
  225. if(upd)
  226. undef(ir);
  227. }
  228. if(trace)
  229. itrace("%s\tf%d,%ld(r%d) %lux=%g",
  230. ci->name, rd, imm, ra, ea, reg.fd[rd]);
  231. putmem_v(ea, reg.dv[rd]);
  232. }
  233. void
  234. stfdx(ulong ir)
  235. {
  236. ulong ea;
  237. int rd, ra, rb, upd;
  238. getarrr(ir);
  239. ea = reg.r[rb];
  240. upd = ((ir>>1)&0x3FF)==759;
  241. if(ra){
  242. ea += reg.r[ra];
  243. if(upd)
  244. reg.r[ra] = ea;
  245. if(trace)
  246. itrace("%s\tf%d,(r%d+r%d) %lux=%g", ci->name, rd, ra, rb, ea, reg.fd[rd]);
  247. } else {
  248. if(upd)
  249. undef(ir);
  250. if(trace)
  251. itrace("%s\tf%d,(r%d) %lux=%g", ci->name, rd, rb, ea, reg.fd[rd]);
  252. }
  253. putmem_v(ea, reg.dv[rd]);
  254. }
  255. void
  256. mcrfs(ulong ir)
  257. {
  258. ulong rd, ra, rb;
  259. static ulong fpscr0[] ={
  260. FPS_FX|FPS_OX,
  261. FPS_UX|FPS_ZX|FPS_XX|FPS_VXSNAN,
  262. FPS_VXISI|FPS_VXIDI|FPS_VXZDZ|FPS_VXIMZ,
  263. FPS_VXVC,
  264. 0,
  265. FPS_VXCVI,
  266. };
  267. getarrr(ir);
  268. if(rb || ra&3 || rd&3)
  269. undef(ir);
  270. ra >>= 2;
  271. rd >>= 2;
  272. reg.cr = (reg.cr & ~mkCR(rd, 0xF)) | mkCR(rd, getCR(ra, reg.fpscr));
  273. reg.fpscr &= ~fpscr0[ra];
  274. if(trace)
  275. itrace("mcrfs\tcrf%d,crf%d\n", rd, ra);
  276. }
  277. void
  278. mffs(ulong ir)
  279. {
  280. int rd, ra, rb;
  281. getarrr(ir);
  282. if(ra || rb)
  283. undef(ir);
  284. reg.dv[rd] = ((uvlong)0xFFF8000L<<16)|reg.fpscr;
  285. /* it's anyone's guess how CR1 should be set when ir&1 */
  286. reg.cr &= ~mkCR(1, 0xE); /* leave SO, reset others */
  287. if(trace)
  288. itrace("mffs%s\tfr%d\n", ir&1?".":"", rd);
  289. }
  290. void
  291. mtfsb1(ulong ir)
  292. {
  293. int rd, ra, rb;
  294. getarrr(ir);
  295. if(ra || rb)
  296. undef(ir);
  297. reg.fpscr |= (1L << (31-rd));
  298. /* BUG: should set summary bits */
  299. if(ir & 1)
  300. reg.cr &= ~mkCR(1, 0xE); /* BUG: manual unclear: leave SO, reset others? */
  301. if(trace)
  302. itrace("mtfsb1%s\tfr%d\n", ir&1?".":"", rd);
  303. }
  304. void
  305. mtfsb0(ulong ir)
  306. {
  307. int rd, ra, rb;
  308. getarrr(ir);
  309. if(ra || rb)
  310. undef(ir);
  311. reg.fpscr &= ~(1L << (31-rd));
  312. if(ir & 1)
  313. reg.cr &= ~mkCR(1, 0xE); /* BUG: manual unclear: leave SO, reset others? */
  314. if(trace)
  315. itrace("mtfsb0%s\tfr%d\n", ir&1?".":"", rd);
  316. }
  317. void
  318. mtfsf(ulong ir)
  319. {
  320. int fm, rb, i;
  321. ulong v;
  322. if(ir & ((1L << 25)|(1L << 16)))
  323. undef(ir);
  324. rb = (ir >> 11) & 0x1F;
  325. fm = (ir >> 17) & 0xFF;
  326. v = reg.dv[rb];
  327. for(i=0; i<8; i++)
  328. if(fm & (1 << (7-i)))
  329. reg.fpscr = (reg.fpscr & ~mkCR(i, 0xF)) | mkCR(i, getCR(i, v));
  330. /* BUG: should set FEX and VX `according to the usual rule' */
  331. if(ir & 1)
  332. reg.cr &= ~mkCR(1, 0xE); /* BUG: manual unclear: leave SO, reset others? */
  333. if(trace)
  334. itrace("mtfsf%s\t#%.2x,fr%d", ir&1?".":"", fm, rb);
  335. }
  336. void
  337. mtfsfi(ulong ir)
  338. {
  339. int imm, rd;
  340. if(ir & ((0x7F << 16)|(1L << 11)))
  341. undef(ir);
  342. rd = (ir >> 23) & 0xF;
  343. imm = (ir >> 12) & 0xF;
  344. reg.fpscr = (reg.fpscr & ~mkCR(rd, 0xF)) | mkCR(rd, imm);
  345. /* BUG: should set FEX and VX `according to the usual rule' */
  346. if(ir & 1)
  347. reg.cr &= ~mkCR(1, 0xE); /* BUG: manual unclear: leave SO, reset others? */
  348. if(trace)
  349. itrace("mtfsfi%s\tcrf%d,#%x", ir&1?".":"", rd, imm);
  350. }
  351. void
  352. fcmp(ulong ir)
  353. {
  354. int fc, rd, ra, rb;
  355. getarrr(ir);
  356. if(rd & 3)
  357. undef(ir);
  358. rd >>= 2;
  359. SET(fc);
  360. switch(getxo(ir)) {
  361. default:
  362. undef(ir);
  363. case 0:
  364. if(trace)
  365. itrace("fcmpu\tcr%d,f%d,f%d", rd, ra, rb);
  366. if(isNaN(reg.fd[ra]) || isNaN(reg.fd[rb])) {
  367. fc = CRFU;
  368. break;
  369. }
  370. if(reg.fd[ra] == reg.fd[rb]) {
  371. fc = CREQ;
  372. break;
  373. }
  374. if(reg.fd[ra] < reg.fd[rb]) {
  375. fc = CRLT;
  376. break;
  377. }
  378. if(reg.fd[ra] > reg.fd[rb]) {
  379. fc = CRGT;
  380. break;
  381. }
  382. print("qi: fcmp error\n");
  383. break;
  384. case 32:
  385. if(trace)
  386. itrace("fcmpo\tcr%d,f%d,f%d", rd, ra, rb);
  387. if(isNaN(reg.fd[ra]) || isNaN(reg.fd[rb])) { /* BUG: depends whether quiet or signalling ... */
  388. fc = CRFU;
  389. Bprint(bioout, "invalid_fp_register\n");
  390. longjmp(errjmp, 0);
  391. }
  392. if(reg.fd[ra] == reg.fd[rb]) {
  393. fc = CREQ;
  394. break;
  395. }
  396. if(reg.fd[ra] < reg.fd[rb]) {
  397. fc = CRLT;
  398. break;
  399. }
  400. if(reg.fd[ra] > reg.fd[rb]) {
  401. fc = CRGT;
  402. break;
  403. }
  404. print("qi: fcmp error\n");
  405. break;
  406. }
  407. fc >>= 28;
  408. reg.cr = (reg.cr & ~mkCR(rd,~0)) | mkCR(rd, fc);
  409. reg.fpscr = (reg.fpscr & ~0xF800) | (fc<<11);
  410. /* BUG: update FX, VXSNAN, VXVC */
  411. }
  412. /*
  413. * the farith functions probably don't produce the right results
  414. * in the presence of NaNs, Infs, etc., esp. wrt exception handling,
  415. */
  416. void
  417. fariths(ulong ir)
  418. {
  419. int rd, ra, rb, rc, fmt;
  420. char *cc;
  421. ulong fpscr;
  422. fmt = 0;
  423. rc = (ir>>6)&0x1F;
  424. getarrr(ir);
  425. switch(getxo(ir)&0x1F) { /* partial XO decode */
  426. default:
  427. undef(ir);
  428. case 18:
  429. if((float)reg.fd[rb] == 0.0) {
  430. Bprint(bioout, "fp_exception ZX\n");
  431. reg.fpscr |= FPS_ZX | FPS_FX;
  432. longjmp(errjmp, 0);
  433. }
  434. reg.fd[rd] = (float)(reg.fd[ra] / reg.fd[rb]);
  435. break;
  436. case 20:
  437. reg.fd[rd] = (float)(reg.fd[ra] - reg.fd[rb]);
  438. break;
  439. case 21:
  440. reg.fd[rd] = (float)(reg.fd[ra] + reg.fd[rb]);
  441. break;
  442. case 25:
  443. reg.fd[rd] = (float)(reg.fd[ra] * reg.fd[rc]);
  444. rb = rc;
  445. break;
  446. case 28:
  447. reg.fd[rd] = (float)((reg.fd[ra] * reg.fd[rc]) - reg.fd[rb]);
  448. fmt = 2;
  449. break;
  450. case 29:
  451. reg.fd[rd] = (float)((reg.fd[ra] * reg.fd[rc]) + reg.fd[rb]);
  452. fmt = 2;
  453. break;
  454. case 30:
  455. reg.fd[rd] = (float)-((reg.fd[ra] * reg.fd[rc]) - reg.fd[rb]);
  456. fmt = 2;
  457. break;
  458. case 31:
  459. reg.fd[rd] = (float)-((reg.fd[ra] * reg.fd[rc]) + reg.fd[rb]);
  460. fmt = 2;
  461. break;
  462. }
  463. if(fmt==1 && ra)
  464. undef(ir);
  465. fpscr = setfpscr();
  466. setfpcc(reg.fd[rd]);
  467. cc = "";
  468. if(ir & 1) {
  469. cc = ".";
  470. reg.cr = (reg.cr & ~mkCR(1, ~0)) | mkCR(1, (fpscr>>28));
  471. }
  472. if(trace) {
  473. switch(fmt) {
  474. case 0:
  475. itrace("%s%s\tfr%d,fr%d,fr%d", ci->name, cc, rd, ra, rb);
  476. break;
  477. case 1:
  478. itrace("%s%s\tfr%d,fr%d", ci->name, cc, rd, rb);
  479. break;
  480. case 2:
  481. itrace("%s%s\tfr%d,fr%d,fr%d,fr%d", ci->name, cc, rd, ra, rc, rb);
  482. break;
  483. }
  484. }
  485. }
  486. void
  487. farith(ulong ir)
  488. {
  489. vlong vl;
  490. int rd, ra, rb, rc, fmt;
  491. char *cc;
  492. ulong fpscr;
  493. int nocc;
  494. double d;
  495. fmt = 0;
  496. nocc = 0;
  497. rc = (ir>>6)&0x1F;
  498. getarrr(ir);
  499. switch(getxo(ir)&0x1F) { /* partial XO decode */
  500. default:
  501. undef(ir);
  502. case 12: /* frsp */
  503. reg.fd[rd] = (float)reg.fd[rb];
  504. fmt = 1;
  505. break;
  506. case 14: /* fctiw */ /* BUG: ignores rounding mode */
  507. case 15: /* fctiwz */
  508. d = reg.fd[rb];
  509. if(d >= 0x7fffffff)
  510. vl = 0x7fffffff;
  511. else if(d < 0x80000000)
  512. vl = 0x80000000;
  513. else
  514. vl = d;
  515. reg.dv[rd] = vl;
  516. fmt = 1;
  517. nocc = 1;
  518. break;
  519. case 18:
  520. if(reg.fd[rb] == 0.0) {
  521. Bprint(bioout, "fp_exception ZX\n");
  522. reg.fpscr |= FPS_ZX | FPS_FX;
  523. longjmp(errjmp, 0);
  524. }
  525. reg.fd[rd] = reg.fd[ra] / reg.fd[rb];
  526. break;
  527. case 20:
  528. reg.fd[rd] = reg.fd[ra] - reg.fd[rb];
  529. break;
  530. case 21:
  531. reg.fd[rd] = reg.fd[ra] + reg.fd[rb];
  532. break;
  533. case 25:
  534. reg.fd[rd] = reg.fd[ra] * reg.fd[rc];
  535. rb = rc;
  536. break;
  537. case 28:
  538. reg.fd[rd] = (reg.fd[ra] * reg.fd[rc]) - reg.fd[rb];
  539. fmt = 2;
  540. break;
  541. case 29:
  542. reg.fd[rd] = (reg.fd[ra] * reg.fd[rc]) + reg.fd[rb];
  543. fmt = 2;
  544. break;
  545. case 30:
  546. reg.fd[rd] = -((reg.fd[ra] * reg.fd[rc]) - reg.fd[rb]);
  547. fmt = 2;
  548. break;
  549. case 31:
  550. reg.fd[rd] = -((reg.fd[ra] * reg.fd[rc]) + reg.fd[rb]);
  551. fmt = 2;
  552. break;
  553. }
  554. if(fmt==1 && ra)
  555. undef(ir);
  556. fpscr = setfpscr();
  557. if(nocc == 0)
  558. setfpcc(reg.fd[rd]);
  559. cc = "";
  560. if(ir & 1) {
  561. cc = ".";
  562. reg.cr = (reg.cr & ~mkCR(1, ~0)) | mkCR(1, (fpscr>>28));
  563. }
  564. if(trace) {
  565. switch(fmt) {
  566. case 0:
  567. itrace("%s%s\tfr%d,fr%d,fr%d", ci->name, cc, rd, ra, rb);
  568. break;
  569. case 1:
  570. itrace("%s%s\tfr%d,fr%d", ci->name, cc, rd, rb);
  571. break;
  572. case 2:
  573. itrace("%s%s\tfr%d,fr%d,fr%d,fr%d", ci->name, cc, rd, ra, rc, rb);
  574. break;
  575. }
  576. }
  577. }
  578. void
  579. farith2(ulong ir)
  580. {
  581. int rd, ra, rb;
  582. char *cc;
  583. ulong fpscr;
  584. getarrr(ir);
  585. switch(getxo(ir)) { /* full XO decode */
  586. default:
  587. undef(ir);
  588. case 40:
  589. reg.fd[rd] = -reg.fd[rb];
  590. break;
  591. case 72:
  592. reg.fd[rd] = reg.fd[rb];
  593. break;
  594. case 136:
  595. reg.fd[rd] = -fabs(reg.fd[rb]);
  596. break;
  597. case 264:
  598. reg.fd[rd] = fabs(reg.fd[rb]);
  599. break;
  600. }
  601. if(ra)
  602. undef(ir);
  603. fpscr = setfpscr();
  604. setfpcc(reg.fd[rd]);
  605. cc = "";
  606. if(ir & 1) {
  607. cc = ".";
  608. reg.cr = (reg.cr & ~mkCR(1, ~0)) | mkCR(1, (fpscr>>28));
  609. }
  610. if(trace)
  611. itrace("%s%s\tfr%d,fr%d", ci->name, cc, rd, rb);
  612. }
  613. ulong
  614. setfpscr(void)
  615. {
  616. ulong fps, fpscr;
  617. fps = getfsr();
  618. fpscr = reg.fpscr;
  619. if(fps & FPAOVFL)
  620. fpscr |= FPS_OX;
  621. if(fps & FPAINEX)
  622. fpscr |= FPS_XX;
  623. if(fps & FPAUNFL)
  624. fpscr |= FPS_UX;
  625. if(fps & FPAZDIV)
  626. fpscr |= FPS_ZX;
  627. if(fpscr != reg.fpscr) {
  628. fpscr |= FPS_FX;
  629. reg.fpscr = fpscr;
  630. }
  631. return fpscr;
  632. }
  633. void
  634. setfpcc(double r)
  635. {
  636. int c;
  637. c = 0;
  638. if(r == 0)
  639. c |= 2;
  640. else if(r < 0)
  641. c |= 4;
  642. else
  643. c |= 8;
  644. if(isNaN(r))
  645. c |= 1;
  646. reg.fpscr = (reg.fpscr & ~0xF800) | (0<<15) | (c<<11); /* unsure about class bit */
  647. }