float.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include <mach.h>
  5. #define Extern extern
  6. #include "sparc.h"
  7. void
  8. ldf(ulong ir)
  9. {
  10. ulong ea;
  11. int rd, rs1, rs2;
  12. getrop23(ir);
  13. if(ir&IMMBIT) {
  14. ximm(ea, ir);
  15. if(trace)
  16. itrace("ldf\tf%d,0x%lux(r%d) ea=%lux",rd, ea, rs1, ea+reg.r[rs1]);
  17. ea += reg.r[rs1];
  18. }
  19. else {
  20. ea = reg.r[rs1] + reg.r[rs2];
  21. if(trace)
  22. itrace("ldf\tf%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea);
  23. }
  24. reg.di[rd] = getmem_w(ea);
  25. }
  26. void
  27. lddf(ulong ir)
  28. {
  29. ulong ea;
  30. int rd, rs1, rs2;
  31. getrop23(ir);
  32. if(ir&IMMBIT) {
  33. ximm(ea, ir);
  34. if(trace)
  35. itrace("lddf\tf%d,0x%lux(r%d) ea=%lux",
  36. rd, ea, rs1, ea+reg.r[rs1]);
  37. ea += reg.r[rs1];
  38. }
  39. else {
  40. ea = reg.r[rs1] + reg.r[rs2];
  41. if(trace)
  42. itrace("lddf\tf%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea);
  43. }
  44. if(ea&7) {
  45. Bprint(bioout, "mem_address_not_aligned [load addr %.8lux]\n", ea);
  46. longjmp(errjmp, 0);
  47. }
  48. if(rd&1)
  49. undef(ir);
  50. reg.di[rd] = getmem_w(ea);
  51. reg.di[rd+1] = getmem_w(ea+4);
  52. }
  53. void
  54. stf(ulong ir)
  55. {
  56. ulong ea;
  57. int rd, rs1, rs2;
  58. getrop23(ir);
  59. if(ir&IMMBIT) {
  60. ximm(ea, ir);
  61. if(trace)
  62. itrace("stf\tf%d,0x%lux(r%d) %lux=%g",
  63. rd, ea, rs1, ea+reg.r[rs1], reg.fl[rd]);
  64. ea += reg.r[rs1];
  65. }
  66. else {
  67. ea = reg.r[rs1] + reg.r[rs2];
  68. if(trace)
  69. itrace("stf\tf%d,[r%d+r%d] %lux=%lux",
  70. rd, rs1, rs2, ea, reg.r[rd]);
  71. }
  72. putmem_w(ea, reg.di[rd]);
  73. }
  74. void
  75. stdf(ulong ir)
  76. {
  77. ulong ea;
  78. int rd, rs1, rs2;
  79. getrop23(ir);
  80. if(ir&IMMBIT) {
  81. ximm(ea, ir);
  82. if(trace)
  83. itrace("stdf\tf%d,0x%lux(r%d) %lux=%g",
  84. rd, ea, rs1, ea+reg.r[rs1], reg.fl[rd]);
  85. ea += reg.r[rs1];
  86. }
  87. else {
  88. ea = reg.r[rs1] + reg.r[rs2];
  89. if(trace)
  90. itrace("stdf\tf%d,[r%d+r%d] %lux=%lux",
  91. rd, rs1, rs2, ea, reg.r[rd]);
  92. }
  93. if(ea&7) {
  94. Bprint(bioout, "mem_address_not_aligned [store addr %.8lux]\n", ea);
  95. longjmp(errjmp, 0);
  96. }
  97. if(rd&1)
  98. undef(ir);
  99. putmem_w(ea, reg.di[rd]);
  100. putmem_w(ea+4, reg.di[rd+1]);
  101. }
  102. void
  103. fcmp(ulong ir)
  104. {
  105. int fc, rd, rs1, rs2;
  106. getrop23(ir);
  107. USED(rd);
  108. SET(fc);
  109. switch((ir>>5)&0x1FF) {
  110. default:
  111. undef(ir);
  112. case 0x51: /* fcmps */
  113. if(trace)
  114. itrace("fcmps\tf%d,f%d", rs1, rs2);
  115. if(isNaN(reg.fl[rs1]) || isNaN(reg.fl[rs2])) {
  116. fc = 3;
  117. break;
  118. }
  119. if(reg.fl[rs1] == reg.fl[rs2]) {
  120. fc = 0;
  121. break;
  122. }
  123. if(reg.fl[rs1] < reg.fl[rs2]) {
  124. fc = 1;
  125. break;
  126. }
  127. if(reg.fl[rs1] > reg.fl[rs2]) {
  128. fc = 2;
  129. break;
  130. }
  131. print("ki: fcmp error\n");
  132. break;
  133. case 0x52:
  134. if(trace)
  135. itrace("fcmpd\tf%d,f%d", rs1, rs2);
  136. rs1 >>= 1;
  137. rs2 >>= 1;
  138. if(isNaN(reg.fd[rs1]) || isNaN(reg.fd[rs2])) {
  139. fc = 3;
  140. break;
  141. }
  142. if(reg.fd[rs1] == reg.fd[rs2]) {
  143. fc = 0;
  144. break;
  145. }
  146. if(reg.fd[rs1] < reg.fd[rs2]) {
  147. fc = 1;
  148. break;
  149. }
  150. if(reg.fd[rs1] > reg.fd[rs2]) {
  151. fc = 2;
  152. break;
  153. }
  154. print("ki: fcmp error\n");
  155. break;
  156. case 0x55: /* fcmpes */
  157. if(trace)
  158. itrace("fcmpes\tf%d,f%d", rs1, rs2);
  159. rs1 >>= 1;
  160. rs2 >>= 2;
  161. if(isNaN(reg.fl[rs1]) || isNaN(reg.fl[rs2])) {
  162. Bprint(bioout, "invalid_fp_register\n");
  163. longjmp(errjmp, 0);
  164. }
  165. if(reg.fl[rs1] == reg.fl[rs2]) {
  166. fc = 0;
  167. break;
  168. }
  169. if(reg.fl[rs1] < reg.fl[rs2]) {
  170. fc = 1;
  171. break;
  172. }
  173. if(reg.fl[rs1] > reg.fl[rs2]) {
  174. fc = 2;
  175. break;
  176. }
  177. print("ki: fcmp error\n");
  178. break;
  179. case 0x56:
  180. if(trace)
  181. itrace("fcmped\tf%d,f%d", rs1, rs2);
  182. if(isNaN(reg.fd[rs1]) || isNaN(reg.fd[rs2])) {
  183. Bprint(bioout, "invalid_fp_register\n");
  184. longjmp(errjmp, 0);
  185. }
  186. if(reg.fd[rs1] == reg.fd[rs2]) {
  187. fc = 0;
  188. break;
  189. }
  190. if(reg.fd[rs1] < reg.fd[rs2]) {
  191. fc = 1;
  192. break;
  193. }
  194. if(reg.fd[rs1] > reg.fd[rs2]) {
  195. fc = 2;
  196. break;
  197. }
  198. print("ki: fcmp error\n");
  199. break;
  200. }
  201. reg.fpsr = (reg.fpsr&~(0x3<<10)) | (fc<<10);
  202. }
  203. void
  204. fbcc(ulong ir)
  205. {
  206. char *op;
  207. ulong npc;
  208. int takeit, fc, ba, anul;
  209. fc = (reg.fpsr>>10)&3;
  210. ba = 0;
  211. SET(op, takeit);
  212. switch((ir>>25)&0x0F) {
  213. case 0:
  214. op = "fbn";
  215. takeit = 0;
  216. break;
  217. case 1:
  218. op = "fbne";
  219. takeit = fc == FP_L || fc == FP_G || fc == FP_U;
  220. break;
  221. case 2:
  222. op = "fblg";
  223. takeit = fc == FP_L || fc == FP_G;
  224. break;
  225. case 3:
  226. op = "fbul";
  227. takeit = fc == FP_L || fc == FP_U;
  228. break;
  229. case 4:
  230. op = "fbl";
  231. takeit = fc == FP_L;
  232. break;
  233. case 5:
  234. op = "fbug";
  235. takeit = fc == FP_U || fc == FP_G;
  236. break;
  237. case 6:
  238. op = "fbg";
  239. takeit = fc == FP_G;
  240. break;
  241. case 7:
  242. op = "fbu";
  243. takeit = fc == FP_U;
  244. break;
  245. case 8:
  246. op = "fba";
  247. ba = 1;
  248. takeit = 1;
  249. break;
  250. case 9:
  251. op = "fbe";
  252. takeit = fc == FP_E;
  253. break;
  254. case 10:
  255. op = "fbue";
  256. takeit = fc == FP_E || fc == FP_U;
  257. break;
  258. case 11:
  259. op = "fbge";
  260. takeit = fc == FP_E || fc == FP_G;
  261. break;
  262. case 12:
  263. op = "fbuge";
  264. takeit = fc == FP_E || fc == FP_G || fc == FP_U;
  265. break;
  266. case 13:
  267. op = "fble";
  268. takeit = fc == FP_E || fc == FP_L;
  269. break;
  270. case 14:
  271. op = "fbule";
  272. takeit = fc == FP_E || fc == FP_L || fc == FP_U;
  273. break;
  274. case 15:
  275. op = "fbo";
  276. takeit = fc == FP_E || fc == FP_L || fc == FP_G;
  277. break;
  278. }
  279. npc = ir & 0x3FFFFF;
  280. if(npc & (1<<21))
  281. npc |= ~((1<<22)-1);
  282. npc = (npc<<2) + reg.pc;
  283. anul = ir&ANUL;
  284. if(trace) {
  285. if(anul)
  286. itrace("%s,a\t%lux", op, npc);
  287. else
  288. itrace("%s\t%lux", op, npc);
  289. }
  290. if(takeit == 0) {
  291. reg.pc += 4;
  292. if(anul == 0) {
  293. reg.ir = ifetch(reg.pc);
  294. delay(reg.pc+4);
  295. }
  296. else
  297. anulled++;
  298. return;
  299. }
  300. ci->taken++;
  301. if(ba && anul) {
  302. reg.pc = npc-4;
  303. anulled++;
  304. return;
  305. }
  306. reg.ir = ifetch(reg.pc+4);
  307. delay(npc);
  308. reg.pc = npc-4;
  309. }
  310. void
  311. farith(ulong ir)
  312. {
  313. char *op;
  314. long v;
  315. int rd, rs1, rs2, fmt;
  316. fmt = 0;
  317. getrop23(ir);
  318. switch((ir>>5)&0x1FF) {
  319. default:
  320. undef(ir);
  321. case 0x41:
  322. reg.fl[rd] = reg.fl[rs1] + reg.fl[rs2];
  323. op = "fadds";
  324. break;
  325. case 0x42:
  326. reg.fd[rd>>1] = reg.fd[rs1>>1] + reg.fd[rs2>>1];
  327. op = "faddd";
  328. break;
  329. case 0x45:
  330. reg.fl[rd] = reg.fl[rs1] - reg.fl[rs2];
  331. op = "fsubs";
  332. break;
  333. case 0x46:
  334. reg.fd[rd>>1] = reg.fd[rs1>>1] - reg.fd[rs2>>1];
  335. op = "fsubd";
  336. break;
  337. case 0x4d:
  338. if(reg.fl[rs2] == 0.0) {
  339. Bprint(bioout, "fp_exception DZ\n");
  340. longjmp(errjmp, 0);
  341. }
  342. reg.fl[rd] = reg.fl[rs1] / reg.fl[rs2];
  343. op = "fdivs";
  344. break;
  345. case 0x4e:
  346. if(reg.fd[rs2>>1] == 0.0) {
  347. Bprint(bioout, "fp_exception DZ\n");
  348. longjmp(errjmp, 0);
  349. }
  350. reg.fd[rd>>1] = reg.fd[rs1>>1] / reg.fd[rs2>>1];
  351. op = "fdivd";
  352. break;
  353. case 0x49:
  354. reg.fl[rd] = reg.fl[rs1] * reg.fl[rs2];
  355. op = "fmuls";
  356. break;
  357. case 0x4a:
  358. reg.fd[rd>>1] = reg.fd[rs1>>1] * reg.fd[rs2>>1];
  359. op = "fmuld";
  360. break;
  361. case 0xc4:
  362. reg.fl[rd] = (long)reg.di[rs2];
  363. fmt = 1;
  364. op = "fitos";
  365. break;
  366. case 0xc8:
  367. reg.fd[rd>>1] = (long)reg.di[rs2];
  368. fmt = 1;
  369. op = "fitod";
  370. break;
  371. case 0xd1:
  372. v = reg.fl[rs2];
  373. reg.di[rd] = v;
  374. fmt = 1;
  375. op = "fstoi";
  376. break;
  377. case 0xd2:
  378. v = reg.fd[rs2>>1];
  379. reg.di[rd] = v;
  380. fmt = 1;
  381. op = "fdtoi";
  382. break;
  383. case 0x01:
  384. reg.di[rd] = reg.di[rs2];
  385. fmt = 1;
  386. op = "fmovs";
  387. break;
  388. case 0x05:
  389. reg.fl[rd] = -reg.fl[rs2];
  390. fmt = 1;
  391. op = "fnegs";
  392. break;
  393. case 0x09:
  394. reg.fl[rd] = fabs(reg.fl[rs2]);
  395. fmt = 1;
  396. op = "fabss";
  397. break;
  398. case 0xc9:
  399. reg.fd[rd>>1] = reg.fl[rs2];
  400. fmt = 1;
  401. op = "fstod";
  402. break;
  403. case 0xc6:
  404. reg.fl[rd] = reg.fd[rs2>>1];
  405. fmt = 1;
  406. op = "fdtos";
  407. break;
  408. }
  409. if(trace) {
  410. switch(fmt) {
  411. case 0:
  412. itrace("%s\tf%d,f%d,f%d", op, rs1, rs2, rd);
  413. break;
  414. case 1:
  415. itrace("%s\tf%d,f%d", op, rs2, rd);
  416. break;
  417. }
  418. }
  419. }