1 /* Small compiler - Peephole optimizer "sequences" strings (plain
2 * and compressed formats)
4 * Copyright (c) ITB CompuPhase, 2000-2003
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 int strexpand(char *dest, unsigned char *source, int maxlen,
26 unsigned char pairtable[128][2]);
28 #define SCPACK_TERMINATOR , /* end each section with a comma */
30 #define SCPACK_TABLE sequences_table
31 /*-*SCPACK start of pair table, do not change or remove this line */
32 unsigned char sequences_table[][2] = {
33 {32, 37}, {114, 105}, {112, 129}, {46, 130}, {49, 33}, {128, 132}, {97, 100},
34 {46, 97}, {135, 108}, {136, 116}, {111, 134}, {108, 138}, {50, 33}, {115,
36 {128, 140}, {137, 33},
37 {46, 115}, {117, 141}, {112, 145}, {131, 133}, {139, 144}, {112, 143}, {131,
39 {115, 116}, {111, 149}, {112, 152}, {131, 33}, {134, 100}, {110, 151},
40 {111, 156}, {99, 157}, {59, 36},
41 {146, 154}, {148, 150}, {112, 33}, {120, 162}, {101, 163}, {159, 164}, {137,
43 {46, 99}, {122, 101}, {110, 100}, {155, 114}, {101, 113}, {168, 114},
44 {147, 160}, {51, 33}, {128, 174},
45 {103, 33}, {133, 165}, {104, 176}, {99, 178}, {120, 179}, {171, 33}, {106,
47 {173, 161}, {155, 33}, {108, 167}, {117, 169}, {115, 175}, {186, 187},
48 {153, 184}, {141, 185}, {111, 188},
49 {98, 191}, {105, 100}, {115, 103}, {115, 108}, {193, 120}, {182, 133}, {114,
51 {166, 161}, {190, 131}, {137, 142}, {169, 33}, {97, 202}, {139, 147},
52 {172, 111}, {158, 147}, {139, 150},
53 {105, 33}, {101, 115}, {209, 115}, {114, 116}, {148, 147}, {171, 133}, {189,
55 {32, 140}, {146, 167}, {196, 170}, {158, 183}, {170, 183}, {199, 192},
56 {108, 196}, {97, 198}, {194, 211},
57 {46, 208}, {195, 210}, {200, 215}, {112, 222}, {159, 227}, {46, 98}, {118,
59 {111, 230}, {109, 231}, {146, 143}, {99, 144}, {158, 150}, {97, 149},
60 {203, 153}, {52, 33}, {225, 33},
61 {158, 166}, {194, 181}, {195, 181}, {201, 180}, {223, 198}, {153, 203}, {214,
63 {100, 101}, {128, 238}, {119, 236}, {249, 237}, {105, 110}, {115, 250},
64 {232, 143}, {205, 154}
66 /*-*SCPACK end of pair table, do not change or remove this line */
68 #define seqsize(o,p) (opcodes(o)+opargs(p))
73 int savesize; /* number of bytes saved (in bytecode) */
75 static SEQUENCE sequences_cmp[] = {
76 /* A very common sequence in four varieties
77 * load.s.pri n1 load.s.pri n2
78 * push.pri load.s.alt n1
81 * --------------------------------------
82 * load.pri n1 load.s.pri n2
83 * push.pri load.alt n1
86 * --------------------------------------
87 * load.s.pri n1 load.pri n2
88 * push.pri load.s.alt n1
91 * --------------------------------------
92 * load.pri n1 load.pri n2
93 * push.pri load.alt n1
99 "load.s.pri %1!push.pri!load.s.pri %2!pop.alt!",
100 "load.s.pri %2!load.s.alt %1!",
105 seqsize(4, 2) - seqsize(2, 2)},
108 "load.pri %1!push.pri!load.s.pri %2!pop.alt!",
109 "load.s.pri %2!load.alt %1!",
114 seqsize(4, 2) - seqsize(2, 2)},
117 "load.s.pri %1!push.pri!load.pri %2!pop.alt!",
118 "load.pri %2!load.s.alt %1!",
123 seqsize(4, 2) - seqsize(2, 2)},
126 "load.pri %1!push.pri!load.pri %2!pop.alt!",
127 "load.pri %2!load.alt %1!",
132 seqsize(4, 2) - seqsize(2, 2)},
133 /* (#1#) The above also occurs with "addr.pri" (array
134 * indexing) as the first line; so that adds 2 cases.
138 "addr.pri %1!push.pri!load.s.pri %2!pop.alt!",
139 "addr.alt %1!load.s.pri %2!",
144 seqsize(4, 2) - seqsize(2, 2)},
147 "addr.pri %1!push.pri!load.pri %2!pop.alt!",
148 "addr.alt %1!load.pri %2!",
153 seqsize(4, 2) - seqsize(2, 2)},
154 /* And the same sequence with const.pri as either the first
155 * or the second load instruction: four more cases.
159 "const.pri %1!push.pri!load.s.pri %2!pop.alt!",
160 "load.s.pri %2!const.alt %1!",
165 seqsize(4, 2) - seqsize(2, 2)},
168 "const.pri %1!push.pri!load.pri %2!pop.alt!",
169 "load.pri %2!const.alt %1!",
174 seqsize(4, 2) - seqsize(2, 2)},
177 "load.s.pri %1!push.pri!const.pri %2!pop.alt!",
178 "const.pri %2!load.s.alt %1!",
183 seqsize(4, 2) - seqsize(2, 2)},
186 "load.pri %1!push.pri!const.pri %2!pop.alt!",
187 "const.pri %2!load.alt %1!",
192 seqsize(4, 2) - seqsize(2, 2)},
193 /* The same as above, but now with "addr.pri" (array
194 * indexing) on the first line and const.pri on
199 "addr.pri %1!push.pri!const.pri %2!pop.alt!",
200 "addr.alt %1!const.pri %2!",
205 seqsize(4, 2) - seqsize(2, 2)},
206 /* ??? add references */
207 /* Chained relational operators can contain sequences like:
208 * move.pri load.s.pri n1
212 * The above also accurs for "load.pri" and for "const.pri",
213 * so add another two cases.
217 "move.pri!push.pri!load.s.pri %1!pop.alt!",
220 "\350\232\240\324\231",
223 seqsize(4, 1) - seqsize(1, 1)},
226 "move.pri!push.pri!load.pri %1!pop.alt!",
229 "\350\232\240\314\231",
232 seqsize(4, 1) - seqsize(1, 1)},
235 "move.pri!push.pri!const.pri %1!pop.alt!",
238 "\350\232\240\316\231",
241 seqsize(4, 1) - seqsize(1, 1)},
242 /* More optimizations for chained relational operators; the
243 * continuation sequences can be simplified if they turn out
244 * to be termination sequences:
245 * xchg sless also for sless, sgeq and sleq
251 * --------------------------------------
252 * xchg sless also for sless, sgeq and sleq
258 * --------------------------------------
259 * xchg jsgeq n1 also for sless, sgeq and sleq
260 * sgrtr ;$exp (occurs for non-chained comparisons)
263 * --------------------------------------
264 * xchg sless also for sless, sgeq and sleq
265 * sgrtr ;$exp (occurs for non-chained comparisons)
270 "xchg!sgrtr!swap.alt!and!pop.alt!;$exp!",
271 "sless!pop.alt!and!;$exp!",
276 seqsize(5, 0) - seqsize(3, 0)},
279 "xchg!sless!swap.alt!and!pop.alt!;$exp!",
280 "sgrtr!pop.alt!and!;$exp!",
285 seqsize(5, 0) - seqsize(3, 0)},
288 "xchg!sgeq!swap.alt!and!pop.alt!;$exp!",
289 "sleq!pop.alt!and!;$exp!",
294 seqsize(5, 0) - seqsize(3, 0)},
297 "xchg!sleq!swap.alt!and!pop.alt!;$exp!",
298 "sgeq!pop.alt!and!;$exp!",
303 seqsize(5, 0) - seqsize(3, 0)},
306 "xchg!sgrtr!swap.alt!and!pop.alt!jzer %1!",
307 "sless!pop.alt!and!jzer %1!",
312 seqsize(5, 0) - seqsize(3, 0)},
315 "xchg!sless!swap.alt!and!pop.alt!jzer %1!",
316 "sgrtr!pop.alt!and!jzer %1!",
321 seqsize(5, 0) - seqsize(3, 0)},
324 "xchg!sgeq!swap.alt!and!pop.alt!jzer %1!",
325 "sleq!pop.alt!and!jzer %1!",
330 seqsize(5, 0) - seqsize(3, 0)},
333 "xchg!sleq!swap.alt!and!pop.alt!jzer %1!",
334 "sgeq!pop.alt!and!jzer %1!",
339 seqsize(5, 0) - seqsize(3, 0)},
342 "xchg!sgrtr!jzer %1!;$exp!",
348 seqsize(3, 1) - seqsize(1, 1)},
351 "xchg!sless!jzer %1!;$exp!",
357 seqsize(3, 1) - seqsize(1, 1)},
360 "xchg!sgeq!jzer %1!;$exp!",
366 seqsize(3, 1) - seqsize(1, 1)},
369 "xchg!sleq!jzer %1!;$exp!",
375 seqsize(3, 1) - seqsize(1, 1)},
384 seqsize(2, 0) - seqsize(1, 0)},
393 seqsize(2, 0) - seqsize(1, 0)},
402 seqsize(2, 0) - seqsize(1, 0)},
411 seqsize(2, 0) - seqsize(1, 0)},
412 /* The entry to chained operators is also opt to optimization
413 * load.s.pri n1 load.s.pri n2
414 * load.s.alt n2 load.s.alt n1
416 * --------------------------------------
417 * load.s.pri n1 load.pri n2
418 * load.alt n2 load.s.alt n1
420 * --------------------------------------
421 * load.s.pri n1 const.pri n2
422 * const.alt n2 load.s.alt n1
424 * --------------------------------------
425 * and all permutations...
429 "load.s.pri %1!load.s.alt %2!xchg!",
430 "load.s.pri %2!load.s.alt %1!",
435 seqsize(3, 2) - seqsize(2, 2)},
438 "load.s.pri %1!load.alt %2!xchg!",
439 "load.pri %2!load.s.alt %1!",
444 seqsize(3, 2) - seqsize(2, 2)},
447 "load.s.pri %1!const.alt %2!xchg!",
448 "const.pri %2!load.s.alt %1!",
453 seqsize(3, 2) - seqsize(2, 2)},
456 "load.pri %1!load.s.alt %2!xchg!",
457 "load.s.pri %2!load.alt %1!",
462 seqsize(3, 2) - seqsize(2, 2)},
465 "load.pri %1!load.alt %2!xchg!",
466 "load.pri %2!load.alt %1!",
471 seqsize(3, 2) - seqsize(2, 2)},
474 "load.pri %1!const.alt %2!xchg!",
475 "const.pri %2!load.alt %1!",
480 seqsize(3, 2) - seqsize(2, 2)},
483 "const.pri %1!load.s.alt %2!xchg!",
484 "load.s.pri %2!const.alt %1!",
489 seqsize(3, 2) - seqsize(2, 2)},
492 "const.pri %1!load.alt %2!xchg!",
493 "load.pri %2!const.alt %1!",
498 seqsize(3, 2) - seqsize(2, 2)},
499 /* Array indexing can merit from special instructions.
500 * Simple indexed array lookup can be optimized quite
502 * addr.pri n1 addr.alt n1
503 * push.pri load.s.pri n2
504 * load.s.pri n2 bounds n3
505 * bounds n3 lidx.b n4
511 * And to prepare for storing a value in an array
512 * addr.pri n1 addr.alt n1
513 * push.pri load.s.pri n2
514 * load.s.pri n2 bounds n3
515 * bounds n3 idxaddr.b n4
520 * Notes (additional cases):
521 * 1. instruction addr.pri can also be const.pri (for
523 * 2. the bounds instruction can be absent
524 * 3. when "n4" (the shift value) is the 2 (with 32-bit cels), use the
525 * even more optimal instructions LIDX and IDDXADDR
527 * If the array index is more complex, one can only optimize
528 * the last four instructions:
529 * shl.c.pri n1 pop.alt
533 * --------------------------------------
534 * shl.c.pri n1 pop.alt
535 * pop.alt idxaddr.b n1
539 /* loading from array, "cell" shifted */
542 "addr.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri 2!pop.alt!add!load.i!",
543 "addr.alt %1!load.s.pri %2!bounds %3!lidx!",
548 seqsize(8, 4) - seqsize(4, 3)},
551 "const.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri 2!pop.alt!add!load.i!",
552 "const.alt %1!load.s.pri %2!bounds %3!lidx!",
557 seqsize(8, 4) - seqsize(4, 3)},
560 "addr.pri %1!push.pri!load.s.pri %2!shl.c.pri 2!pop.alt!add!load.i!",
561 "addr.alt %1!load.s.pri %2!lidx!",
566 seqsize(7, 3) - seqsize(3, 2)},
569 "const.pri %1!push.pri!load.s.pri %2!shl.c.pri 2!pop.alt!add!load.i!",
570 "const.alt %1!load.s.pri %2!lidx!",
575 seqsize(7, 3) - seqsize(3, 2)},
577 /* loading from array, not "cell" shifted */
580 "addr.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri %4!pop.alt!add!load.i!",
581 "addr.alt %1!load.s.pri %2!bounds %3!lidx.b %4!",
583 "\333\300\310\370\366",
584 "\252\334\335\345\370",
586 seqsize(8, 4) - seqsize(4, 4)},
589 "const.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri %4!pop.alt!add!load.i!",
590 "const.alt %1!load.s.pri %2!bounds %3!lidx.b %4!",
592 "\332\300\310\370\366",
593 "\236\334\335\345\370",
595 seqsize(8, 4) - seqsize(4, 4)},
598 "addr.pri %1!push.pri!load.s.pri %2!shl.c.pri %3!pop.alt!add!load.i!",
599 "addr.alt %1!load.s.pri %2!lidx.b %3!",
602 "\252\307\335\345\257",
604 seqsize(7, 3) - seqsize(3, 3)},
607 "const.pri %1!push.pri!load.s.pri %2!shl.c.pri %3!pop.alt!add!load.i!",
608 "const.alt %1!load.s.pri %2!lidx.b %3!",
611 "\236\307\335\345\257",
613 seqsize(7, 3) - seqsize(3, 3)},
615 /* array index calculation for storing a value, "cell" aligned */
618 "addr.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri 2!pop.alt!add!",
619 "addr.alt %1!load.s.pri %2!bounds %3!idxaddr!",
624 seqsize(7, 4) - seqsize(4, 3)},
627 "const.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri 2!pop.alt!add!",
628 "const.alt %1!load.s.pri %2!bounds %3!idxaddr!",
633 seqsize(7, 4) - seqsize(4, 3)},
636 "addr.pri %1!push.pri!load.s.pri %2!shl.c.pri 2!pop.alt!add!",
637 "addr.alt %1!load.s.pri %2!idxaddr!",
642 seqsize(6, 3) - seqsize(3, 2)},
645 "const.pri %1!push.pri!load.s.pri %2!shl.c.pri 2!pop.alt!add!",
646 "const.alt %1!load.s.pri %2!idxaddr!",
651 seqsize(6, 3) - seqsize(3, 2)},
653 /* array index calculation for storing a value, not "cell" packed */
656 "addr.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri %4!pop.alt!add!",
657 "addr.alt %1!load.s.pri %2!bounds %3!idxaddr.b %4!",
659 "\333\300\310\370\275",
660 "\252\334\331\345\370",
662 seqsize(7, 4) - seqsize(4, 4)},
665 "const.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri %4!pop.alt!add!",
666 "const.alt %1!load.s.pri %2!bounds %3!idxaddr.b %4!",
668 "\332\300\310\370\275",
669 "\236\334\331\345\370",
671 seqsize(7, 4) - seqsize(4, 4)},
674 "addr.pri %1!push.pri!load.s.pri %2!shl.c.pri %3!pop.alt!add!",
675 "addr.alt %1!load.s.pri %2!idxaddr.b %3!",
678 "\252\307\331\345\257",
680 seqsize(6, 3) - seqsize(3, 3)},
683 "const.pri %1!push.pri!load.s.pri %2!shl.c.pri %3!pop.alt!add!",
684 "const.alt %1!load.s.pri %2!idxaddr.b %3!",
687 "\236\307\331\345\257",
689 seqsize(6, 3) - seqsize(3, 3)},
691 /* the shorter array indexing sequences, see above for comments */
694 "shl.c.pri 2!pop.alt!add!loadi!",
700 seqsize(4, 1) - seqsize(2, 0)},
703 "shl.c.pri 2!pop.alt!add!",
709 seqsize(3, 1) - seqsize(2, 0)},
713 "shl.c.pri %1!pop.alt!add!loadi!",
714 "pop.alt!lidx.b %1!",
719 seqsize(4, 1) - seqsize(2, 1)},
722 "shl.c.pri %1!pop.alt!add!",
723 "pop.alt!idxaddr.b %1!",
728 seqsize(3, 1) - seqsize(2, 1)},
729 /* For packed arrays, there is another case (packed arrays
730 * do not take advantage of the LIDX or IDXADDR instructions).
731 * addr.pri n1 addr.alt n1
732 * push.pri load.s.pri n2
733 * load.s.pri n2 bounds n3
737 * Notes (additional cases):
738 * 1. instruction addr.pri can also be const.pri (for
740 * 2. the bounds instruction can be absent, but that
741 * case is already handled (see #1#)
745 "addr.pri %1!push.pri!load.s.pri %2!bounds %3!pop.alt!",
746 "addr.alt %1!load.s.pri %2!bounds %3!",
751 seqsize(5, 3) - seqsize(3, 3)},
754 "const.pri %1!push.pri!load.s.pri %2!bounds %3!pop.alt!",
755 "const.alt %1!load.s.pri %2!bounds %3!",
760 seqsize(5, 3) - seqsize(3, 3)},
761 /* During a calculation, the intermediate result must sometimes
762 * be moved from PRI to ALT, like in:
764 * load.s.pri n1 load.s.pri n1
767 * The above also accurs for "load.pri" and for "const.pri",
768 * so add another two cases.
772 "push.pri!load.s.pri %1!pop.alt!",
773 "move.alt!load.s.pri %1!",
778 seqsize(3, 1) - seqsize(2, 1)},
781 "push.pri!load.pri %1!pop.alt!",
782 "move.alt!load.pri %1!",
787 seqsize(3, 1) - seqsize(2, 1)},
790 "push.pri!const.pri %1!pop.alt!",
791 "move.alt!const.pri %1!",
796 seqsize(3, 1) - seqsize(2, 1)},
799 "push.pri!zero.pri!pop.alt!",
800 "move.alt!zero.pri!",
805 seqsize(3, 0) - seqsize(2, 0)},
806 /* saving PRI and then loading from its address
807 * occurs when indexing a multi-dimensional array
811 "push.pri!load.i!pop.alt!",
817 seqsize(3, 0) - seqsize(2, 0)},
818 /* An even simpler PUSH/POP optimization (occurs in
819 * switch statements):
831 seqsize(2, 0) - seqsize(1, 0)},
832 /* And what to think of this PUSH/POP sequence, which occurs
833 * due to the support for user-defined assignment operator):
840 // "push.alt!pop.alt!",
841 // ";$", /* SCPACK cannot handle empty strings */
846 // seqsize(2,0) - seqsize(0,0)
848 /* Functions with many parameters with the same default
849 * value have sequences like:
850 * push.c n1 const.pri n1
851 * ;$par push.r.pri n2 ; where n2 is the number of pushes
857 * The shortest matched sequence is 3, because a sequence of two can also be
858 * optimized as two "push.c n1" instructions.
859 * => this optimization does not work, because the argument re-ordering in
860 * a function call causes each argument to be optimized individually
864 // "const.pri %1!push.pri!;$par!const.pri %1!push.pri!;$par!const.pri %1!push.pri!;$par!const.pri %1!push.pri!;$par!const.pri %1!push.pri!;$par!",
865 // "const.pri %1!push.r.pri 5!;$par!",
868 // "\352\221.r\2745!",
870 // seqsize(10,5) - seqsize(2,2)
874 // "const.pri %1!push.pri!;$par!const.pri %1!push.pri!;$par!const.pri %1!push.pri!;$par!const.pri %1!push.pri!;$par!",
875 // "const.pri %1!push.r.pri 4!;$par!",
878 // "\352\221.r\274\326",
880 // seqsize(8,4) - seqsize(2,2)
884 // "const.pri %1!push.pri!;$par!const.pri %1!push.pri!;$par!const.pri %1!push.pri!;$par!",
885 // "const.pri %1!push.r.pri 3!;$par!",
888 // "\352\221.r\274\247",
890 // seqsize(6,3) - seqsize(2,2)
892 /* User-defined operators first load the operands into registers and
893 * then have them pushed onto the stack. This can give rise to sequences
895 * const.pri n1 push.c n1
896 * const.alt n2 push.c n2
899 * A similar sequence occurs with the two PUSH.pri/alt instructions inverted.
900 * The first, second, or both CONST.pri/alt instructions can also be
902 * This gives 2 x 4 cases.
906 "const.pri %1!const.alt %2!push.pri!push.alt!",
907 "push.c %1!push.c %2!",
909 "\316\236\311\240\351",
912 seqsize(4, 2) - seqsize(2, 2)},
915 "const.pri %1!const.alt %2!push.alt!push.pri!",
916 "push.c %2!push.c %1!",
918 "\316\236\311\351\240",
921 seqsize(4, 2) - seqsize(2, 2)},
924 "const.pri %1!load.alt %2!push.pri!push.alt!",
925 "push.c %1!push %2!",
927 "\316\213\311\240\351",
930 seqsize(4, 2) - seqsize(2, 2)},
933 "const.pri %1!load.alt %2!push.alt!push.pri!",
934 "push %2!push.c %1!",
936 "\316\213\311\351\240",
939 seqsize(4, 2) - seqsize(2, 2)},
942 "load.pri %1!const.alt %2!push.pri!push.alt!",
943 "push %1!push.c %2!",
945 "\314\236\311\240\351",
948 seqsize(4, 2) - seqsize(2, 2)},
951 "load.pri %1!const.alt %2!push.alt!push.pri!",
952 "push.c %2!push %1!",
954 "\314\236\311\351\240",
957 seqsize(4, 2) - seqsize(2, 2)},
960 "load.pri %1!load.alt %2!push.pri!push.alt!",
963 "\314\213\311\240\351",
966 seqsize(4, 2) - seqsize(2, 2)},
969 "load.pri %1!load.alt %2!push.alt!push.pri!",
972 "\314\213\311\351\240",
975 seqsize(4, 2) - seqsize(2, 2)},
976 /* Function calls (parameters are passed on the stack)
977 * load.s.pri n1 push.s n1
979 * --------------------------------------
980 * load.pri n1 push n1
982 * --------------------------------------
983 * const.pri n1 push.c n1
985 * --------------------------------------
988 * --------------------------------------
989 * addr.pri n1 pushaddr n1
992 * However, PRI must not be needed after this instruction
993 * if this shortcut is used. Check for the ;$par comment.
997 "load.s.pri %1!push.pri!;$par!",
1003 seqsize(2, 1) - seqsize(1, 1)},
1006 "load.pri %1!push.pri!;$par!",
1012 seqsize(2, 1) - seqsize(1, 1)},
1015 "const.pri %1!push.pri!;$par!",
1021 seqsize(2, 1) - seqsize(1, 1)},
1024 "zero.pri!push.pri!;$par!",
1030 seqsize(2, 0) - seqsize(1, 1)},
1033 "addr.pri %1!push.pri!;$par!",
1034 "pushaddr %1!;$par!",
1039 seqsize(2, 1) - seqsize(1, 1)},
1040 /* References with a default value generate new cells on the heap
1041 * dynamically. That code often ends with:
1047 "move.pri!push.pri!",
1053 seqsize(2, 0) - seqsize(1, 0)},
1054 /* Simple arithmetic operations on constants. Noteworthy is the
1055 * subtraction of a constant, since it is converted to the addition
1056 * of the inverse value.
1057 * const.alt n1 add.c n1
1059 * --------------------------------------
1060 * const.alt n1 add.c -n1
1062 * --------------------------------------
1063 * const.alt n1 smul.c n1
1065 * --------------------------------------
1066 * const.alt n1 eq.c.pri n1
1071 "const.alt %1!add!",
1077 seqsize(2, 1) - seqsize(1, 1)},
1080 "const.alt %1!sub!",
1086 seqsize(2, 1) - seqsize(1, 1)},
1089 "const.alt %1!smul!",
1095 seqsize(2, 1) - seqsize(1, 1)},
1104 seqsize(2, 1) - seqsize(1, 1)},
1105 /* Some operations use the alternative subtraction operation --these
1106 * can also be optimized.
1107 * const.pri n1 load.s.pri n2
1108 * load.s.alt n2 add.c -n1
1110 * --------------------------------------
1111 * const.pri n1 load.pri n2
1112 * load.alt n2 add.c -n1
1117 "const.pri %1!load.s.alt %2!sub.alt!",
1118 "load.s.pri %2!add.c -%1!",
1120 "\316\224\311sub\217",
1121 "\241\233\247 -%\204",
1123 seqsize(3, 2) - seqsize(2, 2)},
1126 "const.pri %1!load.alt %2!sub.alt!",
1127 "load.pri %2!add.c -%1!",
1129 "\316\213\311sub\217",
1130 "\317\233\247 -%\204",
1132 seqsize(3, 2) - seqsize(2, 2)},
1136 * --------------------------------------
1139 * --------------------------------------
1142 * --------------------------------------
1145 * Compares followed by jzer occur much more
1146 * often than compares followed with jnz. So we
1147 * take the easy route here.
1150 * --------------------------------------
1153 * --------------------------------------
1156 * --------------------------------------
1159 * --------------------------------------
1162 * --------------------------------------
1165 * --------------------------------------
1168 * --------------------------------------
1180 seqsize(2, 1) - seqsize(1, 1)},
1189 seqsize(2, 1) - seqsize(1, 1)},
1198 seqsize(2, 1) - seqsize(1, 1)},
1207 seqsize(2, 1) - seqsize(1, 1)},
1216 seqsize(2, 1) - seqsize(1, 1)},
1225 seqsize(2, 1) - seqsize(1, 1)},
1234 seqsize(2, 1) - seqsize(1, 1)},
1243 seqsize(2, 1) - seqsize(1, 1)},
1252 seqsize(2, 1) - seqsize(1, 1)},
1261 seqsize(2, 1) - seqsize(1, 1)},
1270 seqsize(2, 1) - seqsize(1, 1)},
1279 seqsize(2, 1) - seqsize(1, 1)},
1280 /* Test for zero (common case, especially for strings)
1281 * E.g. the test expression of: "for (i=0; str{i}!=0; ++i)"
1285 * --------------------------------------
1297 seqsize(2, 1) - seqsize(1, 1)},
1300 "zero.alt!jneq %1!",
1306 seqsize(2, 1) - seqsize(1, 1)},
1307 /* Incrementing and decrementing leaves a value in
1308 * in PRI which may not be used (for example, as the
1309 * third expression in a "for" loop).
1310 * inc n1 inc n1 ; ++n
1313 * --------------------------------------
1314 * load.pri n1 inc n1 ; n++, e.g. "for (n=0; n<10; n++)"
1317 * Plus the varieties for stack relative increments
1322 "inc %1!load.pri %1!;$exp!",
1325 "\373c\205\314\245",
1328 seqsize(2, 2) - seqsize(1, 1)},
1331 "load.pri %1!inc %1!;$exp!",
1337 seqsize(2, 2) - seqsize(1, 1)},
1340 "inc.s %1!load.s.pri %1!;$exp!",
1343 "\373\352\205\324\245",
1346 seqsize(2, 2) - seqsize(1, 1)},
1349 "load.s.pri %1!inc.s %1!;$exp!",
1355 seqsize(2, 2) - seqsize(1, 1)},
1358 "dec %1!load.pri %1!;$exp!",
1361 "\367c\205\314\245",
1364 seqsize(2, 2) - seqsize(1, 1)},
1367 "load.pri %1!dec %1!;$exp!",
1373 seqsize(2, 2) - seqsize(1, 1)},
1376 "dec.s %1!load.s.pri %1!;$exp!",
1379 "\367\352\205\324\245",
1382 seqsize(2, 2) - seqsize(1, 1)},
1385 "load.s.pri %1!dec.s %1!;$exp!",
1391 seqsize(2, 2) - seqsize(1, 1)},
1392 /* ??? the same (increments and decrements) for references */
1393 /* Loading the constant zero has a special opcode.
1394 * When storing zero in memory, the value of PRI must not be later on.
1395 * const.pri 0 zero n1
1398 * --------------------------------------
1399 * const.pri 0 zero.s n1
1400 * stor.s.pri n1 ;$exp
1402 * --------------------------------------
1406 * --------------------------------------
1407 * zero.pri zero.s n1
1408 * stor.s.pri n1 ;$exp
1410 * --------------------------------------
1411 * const.pri 0 zero.pri
1412 * --------------------------------------
1413 * const.alt 0 zero.alt
1414 * The last two alternatives save more memory than they save
1415 * time, but anyway...
1419 "const.pri 0!stor.pri %1!;$exp!",
1422 "\236\203 0!\227or\223\245",
1425 seqsize(2, 2) - seqsize(1, 1)},
1428 "const.pri 0!stor.s.pri %1!;$exp!",
1431 "\236\203 0!\227or\220\223\245",
1434 seqsize(2, 2) - seqsize(1, 1)},
1437 "zero.pri!stor.pri %1!;$exp!",
1440 "\376\227or\223\245",
1443 seqsize(2, 1) - seqsize(1, 1)},
1446 "zero.pri!stor.s.pri %1!;$exp!",
1449 "\376\227or\220\223\245",
1452 seqsize(2, 1) - seqsize(1, 1)},
1461 seqsize(1, 1) - seqsize(1, 0)},
1470 seqsize(1, 1) - seqsize(1, 0)},