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