1 /* Pawn compiler - Peephole optimizer "sequences" strings (plain
2 * and compressed formats)
4 * Copyright (c) ITB CompuPhase, 2000-2006
6 * This software is provided "as-is", without any express or implied warranty.
7 * In no event will the authors be held liable for any damages arising from
8 * the use of this software.
10 * Permission is granted to anyone to use this software for any purpose,
11 * including commercial applications, and to alter it and redistribute it
12 * freely, subject to the following restrictions:
14 * 1. The origin of this software must not be misrepresented; you must not
15 * claim that you wrote the original software. If you use this software in
16 * a product, an acknowledgment in the product documentation would be
17 * appreciated but is not required.
18 * 2. Altered source versions must be plainly marked as such, and must not be
19 * misrepresented as being the original software.
20 * 3. This notice may not be removed or altered from any source distribution.
25 SC_FUNC int strexpand(char *dest, unsigned char *source, int maxlen, unsigned char pairtable[128][2]);
27 #define SCPACK_TERMINATOR , /* end each section with a comma */
29 #define SCPACK_TABLE sequences_table
30 /*-*SCPACK start of pair table, do not change or remove this line */
31 unsigned char sequences_table[][2] = {
32 {49,33}, {37,128}, {32,129}, {32,37}, {114,105}, {112,132}, {46,133}, {97,100}, {46,97}, {136,108}, {137,116}, {115,104}, {111,135}, {117,139}, {112,141}, {108,140},
33 {131,50}, {144,33}, {46,115}, {138,33}, {59,36}, {134,130}, {143,146}, {115,116}, {134,145}, {110,151}, {111,153}, {99,154}, {112,147}, {135,100}, {134,33}, {114,33},
34 {111,156}, {112,160}, {46,99}, {138,130}, {142,158}, {131,51}, {150,152}, {112,33}, {120,167}, {101,168}, {148,169}, {97,159}, {112,171}, {148,172}, {165,33}, {173,142},
35 {122,101}, {176,114}, {101,113}, {110,100}, {149,164}, {157,114}, {33,161}, {131,49}, {103,33}, {157,33}, {104,184}, {99,186}, {120,187}, {98,111}, {118,101}, {111,190},
36 {109,191}, {130,170}, {131,52}, {106,177}, {138,145}, {180,166}, {192,147}, {108,162}, {163,166}, {143,149}, {115,174}, {117,179}, {139,199}, {203,202}, {189,205}, {105,100},
37 {115,103}, {115,108}, {207,120}, {195,130}, {46,135}, {178,33}, {212,114}, {204,134}, {155,149}, {142,162}, {183,145}, {150,149}, {143,152}, {194,33}, {130,175}, {97,179},
38 {177,111}, {182,185}, {143,46}, {183,144}, {155,152}, {145,175}, {114,101}, {230,102}, {108,231}, {101,115}, {233,115}, {114,116}, {142,147}, {105,33}, {155,163}, {178,130},
39 {215,32}, {240,50}, {143,196}, {155,197}, {181,197}, {181,200}, {108,210}, {46,98}, {241,225}, {208,235}, {209,234}, {224,158}, {143,163}, {150,163}, {155,200}
41 /*-*SCPACK end of pair table, do not change or remove this line */
43 #define seqsize(o,p) (opcodes(o)+opargs(p))
47 int savesize; /* number of bytes saved (in bytecode) */
49 static SEQUENCE sequences_cmp[] = {
50 /* A very common sequence in four varieties
51 * load.s.pri n1 load.s.pri n2
52 * push.pri load.s.alt n1
55 * --------------------------------------
56 * load.pri n1 load.s.pri n2
57 * push.pri load.alt n1
60 * --------------------------------------
61 * load.s.pri n1 load.pri n2
62 * push.pri load.s.alt n1
65 * --------------------------------------
66 * load.pri n1 load.pri n2
67 * push.pri load.alt n1
73 "load.s.pri %1!push.pri!load.s.pri %2!pop.alt!",
74 "load.s.pri %2!load.s.alt %1!",
79 seqsize(4,2) - seqsize(2,2)
83 "load.pri %1!push.pri!load.s.pri %2!pop.alt!",
84 "load.s.pri %2!load.alt %1!",
89 seqsize(4,2) - seqsize(2,2)
93 "load.s.pri %1!push.pri!load.pri %2!pop.alt!",
94 "load.pri %2!load.s.alt %1!",
99 seqsize(4,2) - seqsize(2,2)
103 "load.pri %1!push.pri!load.pri %2!pop.alt!",
104 "load.pri %2!load.alt %1!",
109 seqsize(4,2) - seqsize(2,2)
111 /* (#1#) The above also occurs with "addr.pri" (array
112 * indexing) as the first line; so that adds 2 cases.
116 "addr.pri %1!push.pri!load.s.pri %2!pop.alt!",
117 "addr.alt %1!load.s.pri %2!",
122 seqsize(4,2) - seqsize(2,2)
126 "addr.pri %1!push.pri!load.pri %2!pop.alt!",
127 "addr.alt %1!load.pri %2!",
132 seqsize(4,2) - seqsize(2,2)
134 /* And the same sequence with const.pri as either the first
135 * or the second load instruction: four more cases.
139 "const.pri %1!push.pri!load.s.pri %2!pop.alt!",
140 "load.s.pri %2!const.alt %1!",
145 seqsize(4,2) - seqsize(2,2)
149 "const.pri %1!push.pri!load.pri %2!pop.alt!",
150 "load.pri %2!const.alt %1!",
155 seqsize(4,2) - seqsize(2,2)
159 "load.s.pri %1!push.pri!const.pri %2!pop.alt!",
160 "const.pri %2!load.s.alt %1!",
165 seqsize(4,2) - seqsize(2,2)
169 "load.pri %1!push.pri!const.pri %2!pop.alt!",
170 "const.pri %2!load.alt %1!",
175 seqsize(4,2) - seqsize(2,2)
177 /* The same as above, but now with "addr.pri" (array
178 * indexing) on the first line and const.pri on
183 "addr.pri %1!push.pri!const.pri %2!pop.alt!",
184 "addr.alt %1!const.pri %2!",
189 seqsize(4,2) - seqsize(2,2)
193 "addr.pri %1!push.pri!zero.pri!pop.alt!",
194 "addr.alt %1!zero.pri!",
199 seqsize(4,1) - seqsize(2,1)
201 /* ??? add references */
202 /* Chained relational operators can contain sequences like:
203 * move.pri load.s.pri n1
207 * The above also accurs for "load.pri" and for "const.pri",
208 * so add another two cases.
212 "move.pri!push.pri!load.s.pri %1!pop.alt!",
215 "\300\236\244\333\241",
218 seqsize(4,1) - seqsize(1,1)
222 "move.pri!push.pri!load.pri %1!pop.alt!",
225 "\300\236\244\311\241",
228 seqsize(4,1) - seqsize(1,1)
232 "move.pri!push.pri!const.pri %1!pop.alt!",
235 "\300\236\244\330\241",
238 seqsize(4,1) - seqsize(1,1)
240 /* More optimizations for chained relational operators; the
241 * continuation sequences can be simplified if they turn out
242 * to be termination sequences:
243 * xchg sless also for sless, sgeq and sleq
249 * --------------------------------------
250 * xchg sless also for sless, sgeq and sleq
256 * --------------------------------------
257 * xchg jsgeq n1 also for sless, sgeq and sleq
258 * sgrtr ;$exp (occurs for non-chained comparisons)
261 * --------------------------------------
262 * xchg sless also for sless, sgeq and sleq
263 * sgrtr ;$exp (occurs for non-chained comparisons)
268 "xchg!sgrtr!swap.alt!and!pop.alt!;$exp!",
269 "sless!pop.alt!and!;$exp!",
271 "\274\371\237swa\234\337\266\252",
274 seqsize(5,0) - seqsize(3,0)
278 "xchg!sless!swap.alt!and!pop.alt!;$exp!",
279 "sgrtr!pop.alt!and!;$exp!",
281 "\274\372!swa\234\337\266\252",
282 "\371\237\241\337!\252",
284 seqsize(5,0) - seqsize(3,0)
288 "xchg!sgeq!swap.alt!and!pop.alt!;$exp!",
289 "sleq!pop.alt!and!;$exp!",
291 "\274\320\325swa\234\337\266\252",
292 "\321\262\266\337!\252",
294 seqsize(5,0) - seqsize(3,0)
298 "xchg!sleq!swap.alt!and!pop.alt!;$exp!",
299 "sgeq!pop.alt!and!;$exp!",
301 "\274\321\325swa\234\337\266\252",
302 "\320\262\266\337!\252",
304 seqsize(5,0) - seqsize(3,0)
308 "xchg!sgrtr!swap.alt!and!pop.alt!jzer %1!",
309 "sless!pop.alt!and!jzer %1!",
311 "\274\371\237swa\234\337\266\323",
314 seqsize(5,0) - seqsize(3,0)
318 "xchg!sless!swap.alt!and!pop.alt!jzer %1!",
319 "sgrtr!pop.alt!and!jzer %1!",
321 "\274\372!swa\234\337\266\323",
322 "\371\237\241\337!\323",
324 seqsize(5,0) - seqsize(3,0)
328 "xchg!sgeq!swap.alt!and!pop.alt!jzer %1!",
329 "sleq!pop.alt!and!jzer %1!",
331 "\274\320\325swa\234\337\266\323",
332 "\321\262\266\337!\323",
334 seqsize(5,0) - seqsize(3,0)
338 "xchg!sleq!swap.alt!and!pop.alt!jzer %1!",
339 "sgeq!pop.alt!and!jzer %1!",
341 "\274\321\325swa\234\337\266\323",
342 "\320\262\266\337!\323",
344 seqsize(5,0) - seqsize(3,0)
348 "xchg!sgrtr!jzer %1!;$exp!",
351 "\274\371\237\303\301",
354 seqsize(3,1) - seqsize(1,1)
358 "xchg!sless!jzer %1!;$exp!",
364 seqsize(3,1) - seqsize(1,1)
368 "xchg!sgeq!jzer %1!;$exp!",
371 "\274\320\325\303\301",
374 seqsize(3,1) - seqsize(1,1)
378 "xchg!sleq!jzer %1!;$exp!",
381 "\274\321\325\303\301",
384 seqsize(3,1) - seqsize(1,1)
394 seqsize(2,0) - seqsize(1,0)
404 seqsize(2,0) - seqsize(1,0)
414 seqsize(2,0) - seqsize(1,0)
424 seqsize(2,0) - seqsize(1,0)
426 /* The entry to chained operators is also opt to optimization
427 * load.s.pri n1 load.s.pri n2
428 * load.s.alt n2 load.s.alt n1
430 * --------------------------------------
431 * load.s.pri n1 load.pri n2
432 * load.alt n2 load.s.alt n1
434 * --------------------------------------
435 * load.s.pri n1 const.pri n2
436 * const.alt n2 load.s.alt n1
438 * --------------------------------------
439 * and all permutations...
443 "load.s.pri %1!load.s.alt %2!xchg!",
444 "load.s.pri %2!load.s.alt %1!",
449 seqsize(3,2) - seqsize(2,2)
453 "load.s.pri %1!load.alt %2!xchg!",
454 "load.pri %2!load.s.alt %1!",
459 seqsize(3,2) - seqsize(2,2)
463 "load.s.pri %1!const.alt %2!xchg!",
464 "const.pri %2!load.s.alt %1!",
469 seqsize(3,2) - seqsize(2,2)
473 "load.pri %1!load.s.alt %2!xchg!",
474 "load.s.pri %2!load.alt %1!",
479 seqsize(3,2) - seqsize(2,2)
483 "load.pri %1!load.alt %2!xchg!",
484 "load.pri %2!load.alt %1!",
489 seqsize(3,2) - seqsize(2,2)
493 "load.pri %1!const.alt %2!xchg!",
494 "const.pri %2!load.alt %1!",
499 seqsize(3,2) - seqsize(2,2)
503 "const.pri %1!load.s.alt %2!xchg!",
504 "load.s.pri %2!const.alt %1!",
509 seqsize(3,2) - seqsize(2,2)
513 "const.pri %1!load.alt %2!xchg!",
514 "load.pri %2!const.alt %1!",
519 seqsize(3,2) - seqsize(2,2)
521 /* some sequences where PRI is moved to ALT can be optimized
522 * further when considering what follows
523 * move.alt const.alt n1
526 * (also for load.s.pri and load.pri)
527 * --------------------------------------
528 * lref.pri %1 lref.alt %1
529 * move.alt [load.pri %2]
531 * (where [load.pri %2] may also be another operatrion loading PRI)
535 "move.alt!const.pri %1!xchg!",
541 seqsize(3,1) - seqsize(1,1)
545 "move.alt!load.pri %1!xchg!",
551 seqsize(3,1) - seqsize(1,1)
555 "move.alt!load.s.pri %1!xchg!",
561 seqsize(3,1) - seqsize(1,1)
566 "lref.pri %1!move.alt!load.pri %2!",
567 "lref.alt %1!load.pri %2!",
572 seqsize(3,2) - seqsize(2,2)
576 "lref.pri %1!move.alt!load.s.pri %2!",
577 "lref.alt %1!load.s.pri %2!",
582 seqsize(3,2) - seqsize(2,2)
586 "lref.pri %1!move.alt!const.pri %2!",
587 "lref.alt %1!const.pri %2!",
592 seqsize(3,2) - seqsize(2,2)
596 "lref.s.pri %1!move.alt!load.pri %2!",
597 "lref.s.alt %1!load.pri %2!",
599 "\350\222\225\306\334",
602 seqsize(3,2) - seqsize(2,2)
606 "lref.s.pri %1!move.alt!load.s.pri %2!",
607 "lref.s.alt %1!load.s.pri %2!",
609 "\350\222\225\306\246",
612 seqsize(3,2) - seqsize(2,2)
616 "lref.s.pri %1!move.alt!const.pri %2!",
617 "lref.s.alt %1!const.pri %2!",
619 "\350\222\225\306\344",
622 seqsize(3,2) - seqsize(2,2)
624 /* Array indexing can merit from special instructions.
625 * Simple indexed array lookup can be optimized quite
627 * addr.pri n1 addr.alt n1
628 * push.pri load.s.pri n2
629 * load.s.pri n2 bounds n3
630 * bounds n3 lidx.b n4
636 * And to prepare for storing a value in an array
637 * addr.pri n1 addr.alt n1
638 * push.pri load.s.pri n2
639 * load.s.pri n2 bounds n3
640 * bounds n3 idxaddr.b n4
645 * Notes (additional cases):
646 * 1. instruction addr.pri can also be const.pri (for
648 * 2. the bounds instruction can be absent
649 * 3. when "n4" (the shift value) is the 2 (with 32-bit cells), use the
650 * even more optimal instructions LIDX and IDDXADDR
652 * If the array index is more complex, one can only optimize
653 * the last four instructions:
654 * shl.c.pri n1 pop.alt
658 * --------------------------------------
659 * shl.c.pri n1 pop.alt
660 * pop.alt idxaddr.b n1
664 /* loading from array, "cell" shifted */
667 "addr.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri 2!pop.alt!add!load.i!",
668 "addr.alt %1!load.s.pri %2!bounds %3!lidx!",
670 "\364\316\370\342\355",
673 seqsize(8,4) - seqsize(4,3)
677 "const.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri 2!pop.alt!add!load.i!",
678 "const.alt %1!load.s.pri %2!bounds %3!lidx!",
680 "\363\316\370\342\355",
683 seqsize(8,4) - seqsize(4,3)
687 "addr.pri %1!push.pri!load.s.pri %2!shl.c.pri 2!pop.alt!add!load.i!",
688 "addr.alt %1!load.s.pri %2!lidx!",
693 seqsize(7,3) - seqsize(3,2)
697 "const.pri %1!push.pri!load.s.pri %2!shl.c.pri 2!pop.alt!add!load.i!",
698 "const.alt %1!load.s.pri %2!lidx!",
703 seqsize(7,3) - seqsize(3,2)
706 /* loading from array, not "cell" shifted */
709 "addr.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri %4!pop.alt!add!load.i!",
710 "addr.alt %1!load.s.pri %2!bounds %3!lidx.b %4!",
712 "\364\316\327\302\341\342\355",
713 "\365\316\366\367\335",
715 seqsize(8,4) - seqsize(4,4)
719 "const.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri %4!pop.alt!add!load.i!",
720 "const.alt %1!load.s.pri %2!bounds %3!lidx.b %4!",
722 "\363\316\327\302\341\342\355",
723 "\376\316\366\367\335",
725 seqsize(8,4) - seqsize(4,4)
729 "addr.pri %1!push.pri!load.s.pri %2!shl.c.pri %3!pop.alt!add!load.i!",
730 "addr.alt %1!load.s.pri %2!lidx.b %3!",
732 "\364\327\256\241\271\342\355",
735 seqsize(7,3) - seqsize(3,3)
739 "const.pri %1!push.pri!load.s.pri %2!shl.c.pri %3!pop.alt!add!load.i!",
740 "const.alt %1!load.s.pri %2!lidx.b %3!",
742 "\363\327\256\241\271\342\355",
745 seqsize(7,3) - seqsize(3,3)
748 /* array index calculation for storing a value, "cell" aligned */
751 "addr.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri 2!pop.alt!add!",
752 "addr.alt %1!load.s.pri %2!bounds %3!idxaddr!",
755 "\365\316\322\235\237",
757 seqsize(7,4) - seqsize(4,3)
761 "const.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri 2!pop.alt!add!",
762 "const.alt %1!load.s.pri %2!bounds %3!idxaddr!",
765 "\376\316\322\235\237",
767 seqsize(7,4) - seqsize(4,3)
771 "addr.pri %1!push.pri!load.s.pri %2!shl.c.pri 2!pop.alt!add!",
772 "addr.alt %1!load.s.pri %2!idxaddr!",
777 seqsize(6,3) - seqsize(3,2)
781 "const.pri %1!push.pri!load.s.pri %2!shl.c.pri 2!pop.alt!add!",
782 "const.alt %1!load.s.pri %2!idxaddr!",
787 seqsize(6,3) - seqsize(3,2)
790 /* array index calculation for storing a value, not "cell" packed */
793 "addr.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri %4!pop.alt!add!",
794 "addr.alt %1!load.s.pri %2!bounds %3!idxaddr.b %4!",
796 "\364\316\327\302\341",
797 "\365\316\322\265\367\335",
799 seqsize(7,4) - seqsize(4,4)
803 "const.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri %4!pop.alt!add!",
804 "const.alt %1!load.s.pri %2!bounds %3!idxaddr.b %4!",
806 "\363\316\327\302\341",
807 "\376\316\322\265\367\335",
809 seqsize(7,4) - seqsize(4,4)
813 "addr.pri %1!push.pri!load.s.pri %2!shl.c.pri %3!pop.alt!add!",
814 "addr.alt %1!load.s.pri %2!idxaddr.b %3!",
816 "\364\327\256\241\271",
817 "\365\322\265\367\256",
819 seqsize(6,3) - seqsize(3,3)
823 "const.pri %1!push.pri!load.s.pri %2!shl.c.pri %3!pop.alt!add!",
824 "const.alt %1!load.s.pri %2!idxaddr.b %3!",
826 "\363\327\256\241\271",
827 "\376\322\265\367\256",
829 seqsize(6,3) - seqsize(3,3)
832 /* the shorter array indexing sequences, see above for comments */
835 "shl.c.pri 2!pop.alt!add!loadi!",
841 seqsize(4,1) - seqsize(2,0)
845 "shl.c.pri 2!pop.alt!add!",
851 seqsize(3,1) - seqsize(2,0)
856 "shl.c.pri %1!pop.alt!add!loadi!",
857 "pop.alt!lidx.b %1!",
859 "\314\225\241\271\217\355",
862 seqsize(4,1) - seqsize(2,1)
866 "shl.c.pri %1!pop.alt!add!",
867 "pop.alt!idxaddr.b %1!",
870 "\241\322\265\367\202",
872 seqsize(3,1) - seqsize(2,1)
874 /* For packed arrays, there is another case (packed arrays
875 * do not take advantage of the LIDX or IDXADDR instructions).
876 * addr.pri n1 addr.alt n1
877 * push.pri load.s.pri n2
878 * load.s.pri n2 bounds n3
882 * Notes (additional cases):
883 * 1. instruction addr.pri can also be const.pri (for
885 * 2. the bounds instruction can be absent, but that
886 * case is already handled (see #1#)
890 "addr.pri %1!push.pri!load.s.pri %2!bounds %3!pop.alt!",
891 "addr.alt %1!load.s.pri %2!bounds %3!",
896 seqsize(5,3) - seqsize(3,3)
900 "const.pri %1!push.pri!load.s.pri %2!bounds %3!pop.alt!",
901 "const.alt %1!load.s.pri %2!bounds %3!",
906 seqsize(5,3) - seqsize(3,3)
908 /* Declaration of simple variables often follows the sequence:
909 * ;$lcl <name> <stk> ;$lcl <name> <stk>
910 * stack -4 push.c <constval>
911 * const.pri <constval> ;$exp
917 ";$lcl %1 %2!stack -4!const.pri %3!stor.s.pri %2!;$exp!",
918 ";$lcl %1 %2!push.c %3!;$exp!",
920 "\224lcl\332\227ack -4!\233\206\256\227or\222\230\252",
921 "\224lcl\332\331\256\252",
923 seqsize(3,3) - seqsize(1,1)
927 ";$lcl %1 %2!stack -4!zero.pri!stor.s.pri %2!;$exp!",
928 ";$lcl %1 %2!push.c 0!;$exp!",
930 "\224lcl\332\227ack -4!\373\227or\222\230\252",
931 "\224lcl\332\331 0!\252",
933 seqsize(3,2) - seqsize(1,1)
935 /* During a calculation, the intermediate result must sometimes
936 * be moved from PRI to ALT, like in:
938 * load.s.pri n1 load.s.pri n1
941 * The above also accurs for "load.pri" and for "const.pri",
942 * so add another two cases.
946 "push.pri!load.s.pri %1!pop.alt!",
947 "move.alt!load.s.pri %1!",
952 seqsize(3,1) - seqsize(2,1)
956 "push.pri!load.pri %1!pop.alt!",
957 "move.alt!load.pri %1!",
962 seqsize(3,1) - seqsize(2,1)
966 "push.pri!const.pri %1!pop.alt!",
967 "move.alt!const.pri %1!",
972 seqsize(3,1) - seqsize(2,1)
976 "push.pri!zero.pri!pop.alt!",
977 "move.alt!zero.pri!",
982 seqsize(3,0) - seqsize(2,0)
984 /* saving PRI and then loading from its address
985 * occurs when indexing a multi-dimensional array
989 "push.pri!load.i!pop.alt!",
995 seqsize(3,0) - seqsize(2,0)
997 /* An even simpler PUSH/POP optimization (occurs in
998 * switch statements):
1004 "push.pri!pop.alt!",
1010 seqsize(2,0) - seqsize(1,0)
1012 /* Some simple arithmetic sequences
1016 "move.alt!load.s.pri %1!add!",
1017 "load.s.alt %1!add!",
1022 seqsize(3,1) - seqsize(2,1)
1026 "move.alt!load.pri %1!add!",
1032 seqsize(3,1) - seqsize(2,1)
1036 "move.alt!const.pri %1!add!",
1037 "const.alt %1!add!",
1042 seqsize(3,1) - seqsize(2,1)
1046 "move.alt!load.s.pri %1!sub.alt!",
1047 "load.s.alt %1!sub!",
1052 seqsize(3,1) - seqsize(2,1)
1056 "move.alt!load.pri %1!sub.alt!",
1062 seqsize(3,1) - seqsize(2,1)
1066 "move.alt!const.pri %1!sub.alt!",
1067 "const.alt %1!sub!",
1072 seqsize(3,1) - seqsize(2,1)
1074 /* User-defined operators first load the operands into registers and
1075 * then have them pushed onto the stack. This can give rise to sequences
1077 * const.pri n1 push.c n1
1078 * const.alt n2 push.c n2
1081 * A similar sequence occurs with the two PUSH.pri/alt instructions inverted.
1082 * The first, second, or both CONST.pri/alt instructions can also be
1084 * This gives 2 x 4 cases.
1088 "const.pri %1!const.alt %2!push.pri!push.alt!",
1089 "push.c %1!push.c %2!",
1091 "\330\233\304\244\354",
1094 seqsize(4,2) - seqsize(2,2)
1098 "const.pri %1!const.alt %2!push.alt!push.pri!",
1099 "push.c %2!push.c %1!",
1101 "\330\233\304\354\244",
1104 seqsize(4,2) - seqsize(2,2)
1108 "const.pri %1!load.alt %2!push.pri!push.alt!",
1109 "push.c %1!push %2!",
1114 seqsize(4,2) - seqsize(2,2)
1118 "const.pri %1!load.alt %2!push.alt!push.pri!",
1119 "push %2!push.c %1!",
1124 seqsize(4,2) - seqsize(2,2)
1128 "load.pri %1!const.alt %2!push.pri!push.alt!",
1129 "push %1!push.c %2!",
1131 "\311\233\304\244\354",
1134 seqsize(4,2) - seqsize(2,2)
1138 "load.pri %1!const.alt %2!push.alt!push.pri!",
1139 "push.c %2!push %1!",
1141 "\311\233\304\354\244",
1144 seqsize(4,2) - seqsize(2,2)
1148 "load.pri %1!load.alt %2!push.pri!push.alt!",
1154 seqsize(4,2) - seqsize(2,2)
1158 "load.pri %1!load.alt %2!push.alt!push.pri!",
1164 seqsize(4,2) - seqsize(2,2)
1166 /* Function calls (parameters are passed on the stack)
1167 * load.s.pri n1 push.s n1
1169 * --------------------------------------
1170 * load.pri n1 push n1
1172 * --------------------------------------
1173 * const.pri n1 push.c n1
1175 * --------------------------------------
1178 * --------------------------------------
1179 * addr.pri n1 push.adr n1
1182 * However, PRI must not be needed after this instruction
1183 * if this shortcut is used. Check for the ;$par comment.
1187 "load.s.pri %1!push.pri!;$par!",
1193 seqsize(2,1) - seqsize(1,1)
1197 "load.pri %1!push.pri!;$par!",
1203 seqsize(2,1) - seqsize(1,1)
1207 "const.pri %1!push.pri!;$par!",
1213 seqsize(2,1) - seqsize(1,1)
1217 "zero.pri!push.pri!;$par!",
1223 seqsize(2,0) - seqsize(1,1)
1227 "addr.pri %1!push.pri!;$par!",
1228 "push.adr %1!;$par!",
1233 seqsize(2,1) - seqsize(1,1)
1235 /* References with a default value generate new cells on the heap
1236 * dynamically. That code often ends with:
1242 "move.pri!push.pri!",
1248 seqsize(2,0) - seqsize(1,0)
1250 /* Simple arithmetic operations on constants. Noteworthy is the
1251 * subtraction of a constant, since it is converted to the addition
1252 * of the inverse value.
1253 * const.alt n1 add.c n1
1255 * --------------------------------------
1256 * const.alt n1 add.c -n1
1258 * --------------------------------------
1259 * const.alt n1 smul.c n1
1261 * --------------------------------------
1262 * const.alt n1 eq.c.pri n1
1267 "const.alt %1!add!",
1273 seqsize(2,1) - seqsize(1,1)
1277 "const.alt %1!sub!",
1283 seqsize(2,1) - seqsize(1,1)
1287 "const.alt %1!smul!",
1293 seqsize(2,1) - seqsize(1,1)
1303 seqsize(2,1) - seqsize(1,1)
1305 /* Some operations use the alternative subtraction operation --these
1306 * can also be optimized.
1307 * const.pri n1 load.s.pri n2
1308 * load.s.alt n2 add.c -n1
1310 * --------------------------------------
1311 * const.pri n1 load.pri n2
1312 * load.alt n2 add.c -n1
1317 "const.pri %1!load.s.alt %2!sub.alt!",
1318 "load.s.pri %2!add.c -%1!",
1320 "\330\226\304sub\223",
1321 "\246\235\242 -\201",
1323 seqsize(3,2) - seqsize(2,2)
1327 "const.pri %1!load.alt %2!sub.alt!",
1328 "load.pri %2!add.c -%1!",
1331 "\334\235\242 -\201",
1333 seqsize(3,2) - seqsize(2,2)
1335 /* With arrays indexed with constants that come from enumerations, it happens
1336 * multiple add.c opcodes follow in sequence.
1337 * add.c n1 add.c n1+n2
1342 "add.c %1!add.c %2!",
1345 "\235\242\202\235\242\221",
1348 seqsize(2,2) - seqsize(1,1)
1353 * --------------------------------------
1356 * --------------------------------------
1359 * --------------------------------------
1362 * Compares followed by jzer occur much more
1363 * often than compares followed with jnz. So we
1364 * take the easy route here.
1367 * --------------------------------------
1370 * --------------------------------------
1373 * --------------------------------------
1376 * --------------------------------------
1379 * --------------------------------------
1382 * --------------------------------------
1385 * --------------------------------------
1397 seqsize(2,1) - seqsize(1,1)
1407 seqsize(2,1) - seqsize(1,1)
1417 seqsize(2,1) - seqsize(1,1)
1427 seqsize(2,1) - seqsize(1,1)
1437 seqsize(2,1) - seqsize(1,1)
1447 seqsize(2,1) - seqsize(1,1)
1457 seqsize(2,1) - seqsize(1,1)
1467 seqsize(2,1) - seqsize(1,1)
1477 seqsize(2,1) - seqsize(1,1)
1487 seqsize(2,1) - seqsize(1,1)
1497 seqsize(2,1) - seqsize(1,1)
1507 seqsize(2,1) - seqsize(1,1)
1509 /* Test for zero (common case, especially for strings)
1510 * E.g. the test expression of: "for (i=0; str{i}!=0; ++i)"
1514 * --------------------------------------
1526 seqsize(2,1) - seqsize(1,1)
1530 "zero.alt!jneq %1!",
1536 seqsize(2,1) - seqsize(1,1)
1538 /* Incrementing and decrementing leaves a value in
1539 * in PRI which may not be used (for example, as the
1540 * third expression in a "for" loop).
1541 * inc n1 inc n1 ; ++n
1544 * --------------------------------------
1545 * load.pri n1 inc n1 ; n++, e.g. "for (n=0; n<10; n++)"
1548 * Plus the varieties for stack relative increments
1553 "inc %1!load.pri %1!;$exp!",
1559 seqsize(2,2) - seqsize(1,1)
1563 "load.pri %1!inc %1!;$exp!",
1569 seqsize(2,2) - seqsize(1,1)
1573 "inc.s %1!load.s.pri %1!;$exp!",
1576 "inc\222\202\333\252",
1579 seqsize(2,2) - seqsize(1,1)
1583 "load.s.pri %1!inc.s %1!;$exp!",
1589 seqsize(2,2) - seqsize(1,1)
1593 "dec %1!load.pri %1!;$exp!",
1599 seqsize(2,2) - seqsize(1,1)
1603 "load.pri %1!dec %1!;$exp!",
1609 seqsize(2,2) - seqsize(1,1)
1613 "dec.s %1!load.s.pri %1!;$exp!",
1616 "dec\222\202\333\252",
1619 seqsize(2,2) - seqsize(1,1)
1623 "load.s.pri %1!dec.s %1!;$exp!",
1629 seqsize(2,2) - seqsize(1,1)
1631 /* ??? the same (increments and decrements) for references */
1632 /* Loading the constant zero has a special opcode.
1633 * When storing zero in memory, the value of PRI must not be later on.
1634 * const.pri 0 zero n1
1637 * --------------------------------------
1638 * const.pri 0 zero.s n1
1639 * stor.s.pri n1 ;$exp
1641 * --------------------------------------
1645 * --------------------------------------
1646 * zero.pri zero.s n1
1647 * stor.s.pri n1 ;$exp
1649 * --------------------------------------
1650 * const.pri 0 zero.pri
1651 * --------------------------------------
1652 * const.alt 0 zero.alt
1653 * The last two alternatives save more memory than they save
1654 * time, but anyway...
1658 "const.pri 0!stor.pri %1!;$exp!",
1661 "\233\206 0!\227or\225\252",
1664 seqsize(2,2) - seqsize(1,1)
1668 "const.pri 0!stor.s.pri %1!;$exp!",
1671 "\233\206 0!\227or\222\225\252",
1674 seqsize(2,2) - seqsize(1,1)
1678 "zero.pri!stor.pri %1!;$exp!",
1681 "\373\227or\225\252",
1684 seqsize(2,1) - seqsize(1,1)
1688 "zero.pri!stor.s.pri %1!;$exp!",
1691 "\373\227or\222\225\252",
1694 seqsize(2,1) - seqsize(1,1)
1704 seqsize(1,1) - seqsize(1,0)
1714 seqsize(1,1) - seqsize(1,0)
1717 /* ------------------ */
1718 /* Macro instructions */
1719 /* ------------------ */
1721 { "", "", 0 }, /* separator, so optimizer can stop before generating macro opcodes */
1723 /* optimizing the calling of native functions (which always have a parameter
1724 * count pushed before, and the stack pointer restored afterwards
1728 "push.c %1!sysreq.c %2!stack %3!", //note: %3 == %1 + 4
1731 "\331\202sysr\262\242\221\227ack\256",
1732 "sysr\262.n\220\202",
1734 seqsize(3,3) - seqsize(1,2)
1737 /* Functions with many parameters with the same "type" have sequences like:
1738 * push.c n1 push3.c n1 n2 n3
1746 * Similar sequences occur with PUSH, PUSH.s and PUSHADDR
1750 "push.c %1!;$par!push.c %2!;$par!push.c %3!;$par!push.c %4!;$par!push.c %5!",
1751 "push5.c %1 %2 %3 %4 %5!",
1753 "\331\336\242\345\242\256\257\242\335\257\242\2035!",
1754 "\2165\242\343\245\302\2035!",
1756 seqsize(5,5) - seqsize(1,5)
1760 "push.c %1!;$par!push.c %2!;$par!push.c %3!;$par!push.c %4!",
1761 "push4.c %1 %2 %3 %4!",
1763 "\331\336\242\345\242\256\257\242\335",
1764 "\2164\242\343\245\335",
1766 seqsize(4,4) - seqsize(1,4)
1770 "push.c %1!;$par!push.c %2!;$par!push.c %3!",
1771 "push3.c %1 %2 %3!",
1773 "\331\336\242\345\242\256",
1774 "\2163\242\343\256",
1776 seqsize(3,3) - seqsize(1,3)
1780 "push.c %1!;$par!push.c %2!",
1786 seqsize(2,2) - seqsize(1,2)
1791 "push %1!;$par!push %2!;$par!push %3!;$par!push %4!;$par!push %5!",
1792 "push5 %1 %2 %3 %4 %5!",
1794 "\216\336\345\256\257\335\257\2035!",
1795 "\2165\343\245\302\2035!",
1797 seqsize(5,5) - seqsize(1,5)
1801 "push %1!;$par!push %2!;$par!push %3!;$par!push %4!",
1802 "push4 %1 %2 %3 %4!",
1804 "\216\336\345\256\257\335",
1805 "\2164\343\245\335",
1807 seqsize(4,4) - seqsize(1,4)
1811 "push %1!;$par!push %2!;$par!push %3!",
1817 seqsize(3,3) - seqsize(1,3)
1821 "push %1!;$par!push %2!",
1827 seqsize(2,2) - seqsize(1,2)
1832 "push.s %1!;$par!push.s %2!;$par!push.s %3!;$par!push.s %4!;$par!push.s %5!",
1833 "push5.s %1 %2 %3 %4 %5!",
1835 "\216\222\336\222\345\222\256\257\222\335\257\222\2035!",
1836 "\2165\222\343\245\302\2035!",
1838 seqsize(5,5) - seqsize(1,5)
1842 "push.s %1!;$par!push.s %2!;$par!push.s %3!;$par!push.s %4!",
1843 "push4.s %1 %2 %3 %4!",
1845 "\216\222\336\222\345\222\256\257\222\335",
1846 "\2164\222\343\245\335",
1848 seqsize(4,4) - seqsize(1,4)
1852 "push.s %1!;$par!push.s %2!;$par!push.s %3!",
1853 "push3.s %1 %2 %3!",
1855 "\216\222\336\222\345\222\256",
1856 "\2163\222\343\256",
1858 seqsize(3,3) - seqsize(1,3)
1862 "push.s %1!;$par!push.s %2!",
1865 "\216\222\336\222\221",
1868 seqsize(2,2) - seqsize(1,2)
1873 "push.adr %1!;$par!push.adr %2!;$par!push.adr %3!;$par!push.adr %4!;$par!push.adr %5!",
1874 "push5.adr %1 %2 %3 %4 %5!",
1876 "\216\326\336\326\345\326\256\257\326\335\257\326\2035!",
1877 "\2165\326\343\245\302\2035!",
1879 seqsize(5,5) - seqsize(1,5)
1883 "push.adr %1!;$par!push.adr %2!;$par!push.adr %3!;$par!push.adr %4!",
1884 "push4.adr %1 %2 %3 %4!",
1886 "\216\326\336\326\345\326\256\257\326\335",
1887 "\2164\326\343\245\335",
1889 seqsize(4,4) - seqsize(1,4)
1893 "push.adr %1!;$par!push.adr %2!;$par!push.adr %3!",
1894 "push3.adr %1 %2 %3!",
1896 "\216\326\336\326\345\326\256",
1897 "\2163\326\343\256",
1899 seqsize(3,3) - seqsize(1,3)
1903 "push.adr %1!;$par!push.adr %2!",
1906 "\216\326\336\326\221",
1909 seqsize(2,2) - seqsize(1,2)
1911 /* Loading two registers at a time
1912 * load.pri n1 load.both n1 n2
1914 * --------------------------------------
1915 * load.alt n2 load.both n1 n2
1917 * --------------------------------------
1918 * load.s.pri n1 load.s.both n1 n2
1920 * --------------------------------------
1921 * load.s.alt n2 load.s.both n1 n2
1926 "load.pri %1!load.alt %2!",
1932 seqsize(2,2) - seqsize(1,2)
1936 "load.alt %2!load.pri %1!",
1942 seqsize(2,2) - seqsize(1,2)
1946 "load.s.pri %1!load.s.alt %2!",
1947 "load.s.both %1 %2!",
1952 seqsize(2,2) - seqsize(1,2)
1956 "load.s.alt %2!load.s.pri %1!",
1957 "load.s.both %1 %2!",
1962 seqsize(2,2) - seqsize(1,2)
1964 /* Loading two registers and then pushing them occurs with user operators
1965 * load.both n1 n2 push2 n1 n2
1968 * --------------------------------------
1969 * load.s.both n1 n2 push2.s n1 n2
1975 "load.both %1 %2!push.pri!push.alt!",
1978 "\342\275th\332\244\354",
1981 seqsize(3,2) - seqsize(1,2)
1985 "load.s.both %1 %2!push.pri!push.alt!",
1988 "\226.\275th\332\244\354",
1991 seqsize(3,2) - seqsize(1,2)
1993 /* Load a constant in a variable
1994 * const.pri n1 const n2 n1
1996 * --------------------------------------
1997 * const.pri n1 const.s n2 n1
2002 "const.pri %1!stor.pri %2!",
2008 seqsize(2,2) - seqsize(1,2)
2012 "const.pri %1!stor.s.pri %2!",
2015 "\330\227or\222\230",
2018 seqsize(2,2) - seqsize(1,2)