mul.c 9.0 KB

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