mul.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "gc.h"
  10. /*
  11. * code sequences for multiply by constant.
  12. * [a-l][0-3]
  13. * lsl $(A-'a'),r0,r1
  14. * [+][0-7]
  15. * add r0,r1,r2
  16. * [-][0-7]
  17. * sub r0,r1,r2
  18. */
  19. static int multabp;
  20. static int32_t mulval;
  21. static char* mulcp;
  22. static int32_t valmax;
  23. static int shmax;
  24. static int docode(char *hp, char *cp, int r0, int r1);
  25. static int gen1(int len);
  26. static int gen2(int len, int32_t r1);
  27. static int gen3(int len, int32_t r0, int32_t r1, int flag);
  28. enum
  29. {
  30. SR1 = 1<<0, /* r1 has been shifted */
  31. SR0 = 1<<1, /* r0 has been shifted */
  32. UR1 = 1<<2, /* r1 has not been used */
  33. UR0 = 1<<3, /* r0 has not been used */
  34. };
  35. Multab*
  36. mulcon0(int32_t v)
  37. {
  38. int a1, a2, g;
  39. Multab *m, *m1;
  40. char hint[10];
  41. if(v < 0)
  42. v = -v;
  43. /*
  44. * look in cache
  45. */
  46. m = multab;
  47. for(g=0; g<nelem(multab); g++) {
  48. if(m->val == v) {
  49. if(m->code[0] == 0)
  50. return 0;
  51. return m;
  52. }
  53. m++;
  54. }
  55. /*
  56. * select a spot in cache to overwrite
  57. */
  58. multabp++;
  59. if(multabp < 0 || multabp >= nelem(multab))
  60. multabp = 0;
  61. m = multab+multabp;
  62. m->val = v;
  63. mulval = v;
  64. /*
  65. * look in execption hint table
  66. */
  67. a1 = 0;
  68. a2 = hintabsize;
  69. for(;;) {
  70. if(a1 >= a2)
  71. goto no;
  72. g = (a2 + a1)/2;
  73. if(v < hintab[g].val) {
  74. a2 = g;
  75. continue;
  76. }
  77. if(v > hintab[g].val) {
  78. a1 = g+1;
  79. continue;
  80. }
  81. break;
  82. }
  83. if(docode(hintab[g].hint, m->code, 1, 0))
  84. return m;
  85. print("multiply table failure %ld\n", v);
  86. m->code[0] = 0;
  87. return 0;
  88. no:
  89. /*
  90. * try to search
  91. */
  92. hint[0] = 0;
  93. for(g=1; g<=6; g++) {
  94. if(g >= 6 && v >= 65535)
  95. break;
  96. mulcp = hint+g;
  97. *mulcp = 0;
  98. if(gen1(g)) {
  99. if(docode(hint, m->code, 1, 0))
  100. return m;
  101. print("multiply table failure %ld\n", v);
  102. break;
  103. }
  104. }
  105. /*
  106. * try a recur followed by a shift
  107. */
  108. g = 0;
  109. while(!(v & 1)) {
  110. g++;
  111. v >>= 1;
  112. }
  113. if(g) {
  114. m1 = mulcon0(v);
  115. if(m1) {
  116. strcpy(m->code, m1->code);
  117. sprint(strchr(m->code, 0), "%c0", g+'a');
  118. return m;
  119. }
  120. }
  121. m->code[0] = 0;
  122. return 0;
  123. }
  124. static int
  125. docode(char *hp, char *cp, int r0, int r1)
  126. {
  127. int c, i;
  128. c = *hp++;
  129. *cp = c;
  130. cp += 2;
  131. switch(c) {
  132. default:
  133. c -= 'a';
  134. if(c < 1 || c >= 30)
  135. break;
  136. for(i=0; i<4; i++) {
  137. switch(i) {
  138. case 0:
  139. if(docode(hp, cp, r0<<c, r1))
  140. goto out;
  141. break;
  142. case 1:
  143. if(docode(hp, cp, r1<<c, r1))
  144. goto out;
  145. break;
  146. case 2:
  147. if(docode(hp, cp, r0, r0<<c))
  148. goto out;
  149. break;
  150. case 3:
  151. if(docode(hp, cp, r0, r1<<c))
  152. goto out;
  153. break;
  154. }
  155. }
  156. break;
  157. case '+':
  158. for(i=0; i<8; i++) {
  159. cp[-1] = i+'0';
  160. switch(i) {
  161. case 1:
  162. if(docode(hp, cp, r0+r1, r1))
  163. goto out;
  164. break;
  165. case 5:
  166. if(docode(hp, cp, r0, r0+r1))
  167. goto out;
  168. break;
  169. }
  170. }
  171. break;
  172. case '-':
  173. for(i=0; i<8; i++) {
  174. cp[-1] = i+'0';
  175. switch(i) {
  176. case 1:
  177. if(docode(hp, cp, r0-r1, r1))
  178. goto out;
  179. break;
  180. case 2:
  181. if(docode(hp, cp, r1-r0, r1))
  182. goto out;
  183. break;
  184. case 5:
  185. if(docode(hp, cp, r0, r0-r1))
  186. goto out;
  187. break;
  188. case 6:
  189. if(docode(hp, cp, r0, r1-r0))
  190. goto out;
  191. break;
  192. }
  193. }
  194. break;
  195. case 0:
  196. if(r0 == mulval)
  197. return 1;
  198. }
  199. return 0;
  200. out:
  201. cp[-1] = i+'0';
  202. return 1;
  203. }
  204. static int
  205. gen1(int len)
  206. {
  207. int i;
  208. for(shmax=1; shmax<30; shmax++) {
  209. valmax = 1<<shmax;
  210. if(valmax >= mulval)
  211. break;
  212. }
  213. if(mulval == 1)
  214. return 1;
  215. len--;
  216. for(i=1; i<=shmax; i++)
  217. if(gen2(len, 1<<i)) {
  218. *--mulcp = 'a'+i;
  219. return 1;
  220. }
  221. return 0;
  222. }
  223. static int
  224. gen2(int len, int32_t r1)
  225. {
  226. int i;
  227. if(len <= 0) {
  228. if(r1 == mulval)
  229. return 1;
  230. return 0;
  231. }
  232. len--;
  233. if(len == 0)
  234. goto calcr0;
  235. if(gen3(len, r1, r1+1, UR1)) {
  236. i = '+';
  237. goto out;
  238. }
  239. if(gen3(len, r1-1, r1, UR0)) {
  240. i = '-';
  241. goto out;
  242. }
  243. if(gen3(len, 1, r1+1, UR1)) {
  244. i = '+';
  245. goto out;
  246. }
  247. if(gen3(len, 1, r1-1, UR1)) {
  248. i = '-';
  249. goto out;
  250. }
  251. return 0;
  252. calcr0:
  253. if(mulval == r1+1) {
  254. i = '+';
  255. goto out;
  256. }
  257. if(mulval == r1-1) {
  258. i = '-';
  259. goto out;
  260. }
  261. return 0;
  262. out:
  263. *--mulcp = i;
  264. return 1;
  265. }
  266. static int
  267. gen3(int len, int32_t r0, int32_t r1, int flag)
  268. {
  269. int i, f1, f2;
  270. int32_t x;
  271. if(r0 <= 0 ||
  272. r0 >= r1 ||
  273. r1 > valmax)
  274. return 0;
  275. len--;
  276. if(len == 0)
  277. goto calcr0;
  278. if(!(flag & UR1)) {
  279. f1 = UR1|SR1;
  280. for(i=1; i<=shmax; i++) {
  281. x = r0<<i;
  282. if(x > valmax)
  283. break;
  284. if(gen3(len, r0, x, f1)) {
  285. i += 'a';
  286. goto out;
  287. }
  288. }
  289. }
  290. if(!(flag & UR0)) {
  291. f1 = UR1|SR1;
  292. for(i=1; i<=shmax; i++) {
  293. x = r1<<i;
  294. if(x > valmax)
  295. break;
  296. if(gen3(len, r1, x, f1)) {
  297. i += 'a';
  298. goto out;
  299. }
  300. }
  301. }
  302. if(!(flag & SR1)) {
  303. f1 = UR1|SR1|(flag&UR0);
  304. for(i=1; i<=shmax; i++) {
  305. x = r1<<i;
  306. if(x > valmax)
  307. break;
  308. if(gen3(len, r0, x, f1)) {
  309. i += 'a';
  310. goto out;
  311. }
  312. }
  313. }
  314. if(!(flag & SR0)) {
  315. f1 = UR0|SR0|(flag&(SR1|UR1));
  316. f2 = UR1|SR1;
  317. if(flag & UR1)
  318. f2 |= UR0;
  319. if(flag & SR1)
  320. f2 |= SR0;
  321. for(i=1; i<=shmax; i++) {
  322. x = r0<<i;
  323. if(x > valmax)
  324. break;
  325. if(x > r1) {
  326. if(gen3(len, r1, x, f2)) {
  327. i += 'a';
  328. goto out;
  329. }
  330. } else
  331. if(gen3(len, x, r1, f1)) {
  332. i += 'a';
  333. goto out;
  334. }
  335. }
  336. }
  337. x = r1+r0;
  338. if(gen3(len, r0, x, UR1)) {
  339. i = '+';
  340. goto out;
  341. }
  342. if(gen3(len, r1, x, UR1)) {
  343. i = '+';
  344. goto out;
  345. }
  346. x = r1-r0;
  347. if(gen3(len, x, r1, UR0)) {
  348. i = '-';
  349. goto out;
  350. }
  351. if(x > r0) {
  352. if(gen3(len, r0, x, UR1)) {
  353. i = '-';
  354. goto out;
  355. }
  356. } else
  357. if(gen3(len, x, r0, UR0)) {
  358. i = '-';
  359. goto out;
  360. }
  361. return 0;
  362. calcr0:
  363. f1 = flag & (UR0|UR1);
  364. if(f1 == UR1) {
  365. for(i=1; i<=shmax; i++) {
  366. x = r1<<i;
  367. if(x >= mulval) {
  368. if(x == mulval) {
  369. i += 'a';
  370. goto out;
  371. }
  372. break;
  373. }
  374. }
  375. }
  376. if(mulval == r1+r0) {
  377. i = '+';
  378. goto out;
  379. }
  380. if(mulval == r1-r0) {
  381. i = '-';
  382. goto out;
  383. }
  384. return 0;
  385. out:
  386. *--mulcp = i;
  387. return 1;
  388. }
  389. /*
  390. * hint table has numbers that
  391. * the search algorithm fails on.
  392. * <1000:
  393. * all numbers
  394. * <5000:
  395. * ÷ by 5
  396. * <10000:
  397. * ÷ by 50
  398. * <65536:
  399. * ÷ by 250
  400. */
  401. Hintab hintab[] =
  402. {
  403. 683, "b++d+e+",
  404. 687, "b+e++e-",
  405. 691, "b++d+e+",
  406. 731, "b++d+e+",
  407. 811, "b++d+i+",
  408. 821, "b++e+e+",
  409. 843, "b+d++e+",
  410. 851, "b+f-+e-",
  411. 853, "b++e+e+",
  412. 877, "c++++g-",
  413. 933, "b+c++g-",
  414. 981, "c-+e-d+",
  415. 1375, "b+c+b+h-",
  416. 1675, "d+b++h+",
  417. 2425, "c++f-e+",
  418. 2675, "c+d++f-",
  419. 2750, "b+d-b+h-",
  420. 2775, "c-+g-e-",
  421. 3125, "b++e+g+",
  422. 3275, "b+c+g+e+",
  423. 3350, "c++++i+",
  424. 3475, "c-+e-f-",
  425. 3525, "c-+d+g-",
  426. 3625, "c-+e-j+",
  427. 3675, "b+d+d+e+",
  428. 3725, "b+d-+h+",
  429. 3925, "b+d+f-d-",
  430. 4275, "b+g++e+",
  431. 4325, "b+h-+d+",
  432. 4425, "b+b+g-j-",
  433. 4525, "b+d-d+f+",
  434. 4675, "c++d-g+",
  435. 4775, "b+d+b+g-",
  436. 4825, "c+c-+i-",
  437. 4850, "c++++i-",
  438. 4925, "b++e-g-",
  439. 4975, "c+f++e-",
  440. 5500, "b+g-c+d+",
  441. 6700, "d+b++i+",
  442. 9700, "d++++j-",
  443. 11000, "b+f-c-h-",
  444. 11750, "b+d+g+j-",
  445. 12500, "b+c+e-k+",
  446. 13250, "b+d+e-f+",
  447. 13750, "b+h-c-d+",
  448. 14250, "b+g-c+e-",
  449. 14500, "c+f+j-d-",
  450. 14750, "d-g--f+",
  451. 16750, "b+e-d-n+",
  452. 17750, "c+h-b+e+",
  453. 18250, "d+b+h-d+",
  454. 18750, "b+g-++f+",
  455. 19250, "b+e+b+h+",
  456. 19750, "b++h--f-",
  457. 20250, "b+e-l-c+",
  458. 20750, "c++bi+e-",
  459. 21250, "b+i+l+c+",
  460. 22000, "b+e+d-g-",
  461. 22250, "b+d-h+k-",
  462. 22750, "b+d-e-g+",
  463. 23250, "b+c+h+e-",
  464. 23500, "b+g-c-g-",
  465. 23750, "b+g-b+h-",
  466. 24250, "c++g+m-",
  467. 24750, "b+e+e+j-",
  468. 25000, "b++dh+g+",
  469. 25250, "b+e+d-g-",
  470. 25750, "b+e+b+j+",
  471. 26250, "b+h+c+e+",
  472. 26500, "b+h+c+g+",
  473. 26750, "b+d+e+g-",
  474. 27250, "b+e+e+f+",
  475. 27500, "c-i-c-d+",
  476. 27750, "b+bd++j+",
  477. 28250, "d-d-++i-",
  478. 28500, "c+c-h-e-",
  479. 29000, "b+g-d-f+",
  480. 29500, "c+h+++e-",
  481. 29750, "b+g+f-c+",
  482. 30250, "b+f-g-c+",
  483. 33500, "c-f-d-n+",
  484. 33750, "b+d-b+j-",
  485. 34250, "c+e+++i+",
  486. 35250, "e+b+d+k+",
  487. 35500, "c+e+d-g-",
  488. 35750, "c+i-++e+",
  489. 36250, "b+bh-d+e+",
  490. 36500, "c+c-h-e-",
  491. 36750, "d+e--i+",
  492. 37250, "b+g+g+b+",
  493. 37500, "b+h-b+f+",
  494. 37750, "c+be++j-",
  495. 38500, "b+e+b+i+",
  496. 38750, "d+i-b+d+",
  497. 39250, "b+g-l-+d+",
  498. 39500, "b+g-c+g-",
  499. 39750, "b+bh-c+f-",
  500. 40250, "b+bf+d+g-",
  501. 40500, "b+g-c+g+",
  502. 40750, "c+b+i-e+",
  503. 41250, "d++bf+h+",
  504. 41500, "b+j+c+d-",
  505. 41750, "c+f+b+h-",
  506. 42500, "c+h++g+",
  507. 42750, "b+g+d-f-",
  508. 43250, "b+l-e+d-",
  509. 43750, "c+bd+h+f-",
  510. 44000, "b+f+g-d-",
  511. 44250, "b+d-g--f+",
  512. 44500, "c+e+c+h+",
  513. 44750, "b+e+d-h-",
  514. 45250, "b++g+j-g+",
  515. 45500, "c+d+e-g+",
  516. 45750, "b+d-h-e-",
  517. 46250, "c+bd++j+",
  518. 46500, "b+d-c-j-",
  519. 46750, "e-e-b+g-",
  520. 47000, "b+c+d-j-",
  521. 47250, "b+e+e-g-",
  522. 47500, "b+g-c-h-",
  523. 47750, "b+f-c+h-",
  524. 48250, "d--h+n-",
  525. 48500, "b+c-g+m-",
  526. 48750, "b+e+e-g+",
  527. 49500, "c-f+e+j-",
  528. 49750, "c+c+g++f-",
  529. 50000, "b+e+e+k+",
  530. 50250, "b++i++g+",
  531. 50500, "c+g+f-i+",
  532. 50750, "b+e+d+k-",
  533. 51500, "b+i+c-f+",
  534. 51750, "b+bd+g-e-",
  535. 52250, "b+d+g-j+",
  536. 52500, "c+c+f+g+",
  537. 52750, "b+c+e+i+",
  538. 53000, "b+i+c+g+",
  539. 53500, "c+g+g-n+",
  540. 53750, "b+j+d-c+",
  541. 54250, "b+d-g-j-",
  542. 54500, "c-f+e+f+",
  543. 54750, "b+f-+c+g+",
  544. 55000, "b+g-d-g-",
  545. 55250, "b+e+e+g+",
  546. 55500, "b+cd++j+",
  547. 55750, "b+bh-d-f-",
  548. 56250, "c+d-b+j-",
  549. 56500, "c+d+c+i+",
  550. 56750, "b+e+d++h-",
  551. 57000, "b+d+g-f+",
  552. 57250, "b+f-m+d-",
  553. 57750, "b+i+c+e-",
  554. 58000, "b+e+d+h+",
  555. 58250, "c+b+g+g+",
  556. 58750, "d-e-j--e+",
  557. 59000, "d-i-+e+",
  558. 59250, "e--h-m+",
  559. 59500, "c+c-h+f-",
  560. 59750, "b+bh-e+i-",
  561. 60250, "b+bh-e-e-",
  562. 60500, "c+c-g-g-",
  563. 60750, "b+e-l-e-",
  564. 61250, "b+g-g-c+",
  565. 61750, "b+g-c+g+",
  566. 62250, "f--+c-i-",
  567. 62750, "e+f--+g+",
  568. 64750, "b+f+d+p-",
  569. };
  570. int hintabsize = nelem(hintab);