/*  Pawn compiler - Peephole optimizer "sequences" strings (plain
 *                   and compressed formats)
 *
 *  Copyright (c) ITB CompuPhase, 2000-2005
 *
 *  This software is provided "as-is", without any express or implied warranty.
 *  In no event will the authors be held liable for any damages arising from
 *  the use of this software.
 *
 *  Permission is granted to anyone to use this software for any purpose,
 *  including commercial applications, and to alter it and redistribute it
 *  freely, subject to the following restrictions:
 *
 *  1.  The origin of this software must not be misrepresented; you must not
 *      claim that you wrote the original software. If you use this software in
 *      a product, an acknowledgment in the product documentation would be
 *      appreciated but is not required.
 *  2.  Altered source versions must be plainly marked as such, and must not be
 *      misrepresented as being the original software.
 *  3.  This notice may not be removed or altered from any source distribution.
 *
 *  Version: $Id$
 */

SC_FUNC int strexpand(char *dest, unsigned char *source, int maxlen, unsigned char pairtable[128][2]);

#define SCPACK_TERMINATOR ,     /* end each section with a comma */

#define SCPACK_TABLE sequences_table
/*-*SCPACK start of pair table, do not change or remove this line */
unsigned char sequences_table[][2] = {
  {32,37}, {114,105}, {112,129}, {46,130}, {128,49}, {132,33}, {97,100}, {46,97}, {135,108}, {136,116}, {111,134}, {108,138}, {50,33}, {115,104}, {128,140}, {137,33},
  {46,115}, {117,141}, {112,145}, {131,133}, {139,144}, {112,143}, {131,142}, {115,116}, {131,33}, {59,36}, {134,100}, {111,149}, {112,155}, {110,151}, {111,157}, {99,158},
  {146,152}, {112,33}, {120,161}, {101,162}, {153,163}, {148,150}, {137,133}, {46,99}, {122,101}, {168,114}, {154,114}, {110,100}, {101,113}, {147,160}, {51,33}, {128,174},
  {103,33}, {133,164}, {104,176}, {99,178}, {120,179}, {172,33}, {106,169}, {173,165}, {154,33}, {108,167}, {117,171}, {115,175}, {186,187}, {156,184}, {141,185}, {111,188},
  {98,191}, {105,100}, {115,103}, {115,108}, {193,120}, {182,133}, {114,33}, {166,165}, {190,131}, {137,142}, {171,33}, {97,202}, {169,111}, {139,147}, {159,147}, {139,150},
  {105,33}, {146,167}, {101,115}, {210,115}, {114,116}, {148,147}, {172,133}, {189,139}, {32,140}, {52,33}, {196,170}, {159,183}, {170,183}, {199,192}, {108,196}, {97,198},
  {195,211}, {46,208}, {194,212}, {200,216}, {112,223}, {46,98}, {118,101}, {153,228}, {111,230}, {109,232}, {146,143}, {204,152}, {99,144}, {159,150}, {97,149}, {203,156},
  {224,33}, {159,166}, {194,181}, {195,181}, {201,180}, {226,198}, {156,203}, {128,217}, {215,225}, {100,101}, {238,239}, {105,110}, {115,119}, {252,250}, {154,167}
};
/*-*SCPACK end of pair table, do not change or remove this line */

#define seqsize(o,p)    (opcodes(o)+opargs(p))
typedef struct {
  char *find;
  char *replace;
  int savesize;         /* number of bytes saved (in bytecode) */
} SEQUENCE;
static SEQUENCE sequences_cmp[] = {
  /* A very common sequence in four varieties
   *    load.s.pri n1           load.s.pri n2
   *    push.pri                load.s.alt n1
   *    load.s.pri n2           -
   *    pop.alt                 -
   *    --------------------------------------
   *    load.pri n1             load.s.pri n2
   *    push.pri                load.alt n1
   *    load.s.pri n2           -
   *    pop.alt                 -
   *    --------------------------------------
   *    load.s.pri n1           load.pri n2
   *    push.pri                load.s.alt n1
   *    load.pri n2             -
   *    pop.alt                 -
   *    --------------------------------------
   *    load.pri n1             load.pri n2
   *    push.pri                load.alt n1
   *    load.pri n2             -
   *    pop.alt                 -
   */
  {
    #ifdef SCPACK
      "load.s.pri %1!push.pri!load.s.pri %2!pop.alt!",
      "load.s.pri %2!load.s.alt %1!",
    #else
      "\224\267\234",
      "\245\224\246",
    #endif
    seqsize(4,2) - seqsize(2,2)
  },
  {
    #ifdef SCPACK
      "load.pri %1!push.pri!load.s.pri %2!pop.alt!",
      "load.s.pri %2!load.alt %1!",
    #else
      "\213\267\234",
      "\245\213\246",
    #endif
    seqsize(4,2) - seqsize(2,2)
  },
  {
    #ifdef SCPACK
      "load.s.pri %1!push.pri!load.pri %2!pop.alt!",
      "load.pri %2!load.s.alt %1!",
    #else
      "\224\255\317\234",
      "\317\224\246",
    #endif
    seqsize(4,2) - seqsize(2,2)
  },
  {
    #ifdef SCPACK
      "load.pri %1!push.pri!load.pri %2!pop.alt!",
      "load.pri %2!load.alt %1!",
    #else
      "\213\255\317\234",
      "\317\213\246",
    #endif
    seqsize(4,2) - seqsize(2,2)
  },
  /* (#1#) The above also occurs with "addr.pri" (array
   * indexing) as the first line; so that adds 2 cases.
   */
  {
    #ifdef SCPACK
      "addr.pri %1!push.pri!load.s.pri %2!pop.alt!",
      "addr.alt %1!load.s.pri %2!",
    #else
      "\334\234",
      "\252\307",
    #endif
    seqsize(4,2) - seqsize(2,2)
  },
  {
    #ifdef SCPACK
      "addr.pri %1!push.pri!load.pri %2!pop.alt!",
      "addr.alt %1!load.pri %2!",
    #else
      "\252\255\317\234",
      "\252\246\317",
    #endif
    seqsize(4,2) - seqsize(2,2)
  },
  /* And the same sequence with const.pri as either the first
   * or the second load instruction: four more cases.
   */
  {
    #ifdef SCPACK
      "const.pri %1!push.pri!load.s.pri %2!pop.alt!",
      "load.s.pri %2!const.alt %1!",
    #else
      "\333\234",
      "\245\361",
    #endif
    seqsize(4,2) - seqsize(2,2)
  },
  {
    #ifdef SCPACK
      "const.pri %1!push.pri!load.pri %2!pop.alt!",
      "load.pri %2!const.alt %1!",
    #else
      "\237\255\317\234",
      "\317\361",
    #endif
    seqsize(4,2) - seqsize(2,2)
  },
  {
    #ifdef SCPACK
      "load.s.pri %1!push.pri!const.pri %2!pop.alt!",
      "const.pri %2!load.s.alt %1!",
    #else
      "\224\255\355\234",
      "\355\224\246",
    #endif
    seqsize(4,2) - seqsize(2,2)
  },
  {
    #ifdef SCPACK
      "load.pri %1!push.pri!const.pri %2!pop.alt!",
      "const.pri %2!load.alt %1!",
    #else
      "\213\255\355\234",
      "\355\213\246",
    #endif
    seqsize(4,2) - seqsize(2,2)
  },
  /* The same as above, but now with "addr.pri" (array
   * indexing) on the first line and const.pri on
   * the second.
   */
  {
    #ifdef SCPACK
      "addr.pri %1!push.pri!const.pri %2!pop.alt!",
      "addr.alt %1!const.pri %2!",
    #else
      "\252\255\355\234",
      "\252\246\355",
    #endif
    seqsize(4,2) - seqsize(2,2)
  },
  {
    #ifdef SCPACK
      "addr.pri %1!push.pri!zero.pri!pop.alt!",
      "addr.alt %1!zero.pri!",
    #else
      "\252\255\353\234",
      "\252\246\353",
    #endif
    seqsize(4,1) - seqsize(2,1)
  },
  /* ??? add references */
  /* Chained relational operators can contain sequences like:
   *    move.pri                load.s.pri n1
   *    push.pri                -
   *    load.s.pri n1           -
   *    pop.alt                 -
   * The above also accurs for "load.pri" and for "const.pri",
   * so add another two cases.
   */
  {
    #ifdef SCPACK
      "move.pri!push.pri!load.s.pri %1!pop.alt!",
      "load.s.pri %1!",
    #else
      "\351\230\240\325\234",
      "\325",
    #endif
    seqsize(4,1) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "move.pri!push.pri!load.pri %1!pop.alt!",
      "load.pri %1!",
    #else
      "\351\230\240\315\234",
      "\315",
    #endif
    seqsize(4,1) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "move.pri!push.pri!const.pri %1!pop.alt!",
      "const.pri %1!",
    #else
      "\351\230\240\316\234",
      "\316",
    #endif
    seqsize(4,1) - seqsize(1,1)
  },
  /* More optimizations for chained relational operators; the
   * continuation sequences can be simplified if they turn out
   * to be termination sequences:
   *    xchg                    sless       also for sless, sgeq and sleq
   *    sgrtr                   pop.alt
   *    swap.alt                and
   *    and                     ;$exp
   *    pop.alt                 -
   *    ;$exp                   -
   *    --------------------------------------
   *    xchg                    sless       also for sless, sgeq and sleq
   *    sgrtr                   pop.alt
   *    swap.alt                and
   *    and                     jzer n1
   *    pop.alt                 -
   *    jzer n1                 -
   *    --------------------------------------
   *    xchg                    jsgeq  n1   also for sless, sgeq and sleq
   *    sgrtr                   ;$exp       (occurs for non-chained comparisons)
   *    jzer n1                 -
   *    ;$exp                   -
   *    --------------------------------------
   *    xchg                    sless       also for sless, sgeq and sleq
   *    sgrtr                   ;$exp       (occurs for non-chained comparisons)
   *    ;$exp                   -
   */
  {
    #ifdef SCPACK
      "xchg!sgrtr!swap.alt!and!pop.alt!;$exp!",
      "sless!pop.alt!and!;$exp!",
    #else
      "\264\365\375\244",
      "\360\366\244",
    #endif
    seqsize(5,0) - seqsize(3,0)
  },
  {
    #ifdef SCPACK
      "xchg!sless!swap.alt!and!pop.alt!;$exp!",
      "sgrtr!pop.alt!and!;$exp!",
    #else
      "\264\360\375\244",
      "\365\366\244",
    #endif
    seqsize(5,0) - seqsize(3,0)
  },
  {
    #ifdef SCPACK
      "xchg!sgeq!swap.alt!and!pop.alt!;$exp!",
      "sleq!pop.alt!and!;$exp!",
    #else
      "\264\362\375\244",
      "\363\366\244",
    #endif
    seqsize(5,0) - seqsize(3,0)
  },
  {
    #ifdef SCPACK
      "xchg!sleq!swap.alt!and!pop.alt!;$exp!",
      "sgeq!pop.alt!and!;$exp!",
    #else
      "\264\363\375\244",
      "\362\366\244",
    #endif
    seqsize(5,0) - seqsize(3,0)
  },
  {
    #ifdef SCPACK
      "xchg!sgrtr!swap.alt!and!pop.alt!jzer %1!",
      "sless!pop.alt!and!jzer %1!",
    #else
      "\264\365\375\305",
      "\360\366\305",
    #endif
    seqsize(5,0) - seqsize(3,0)
  },
  {
    #ifdef SCPACK
      "xchg!sless!swap.alt!and!pop.alt!jzer %1!",
      "sgrtr!pop.alt!and!jzer %1!",
    #else
      "\264\360\375\305",
      "\365\366\305",
    #endif
    seqsize(5,0) - seqsize(3,0)
  },
  {
    #ifdef SCPACK
      "xchg!sgeq!swap.alt!and!pop.alt!jzer %1!",
      "sleq!pop.alt!and!jzer %1!",
    #else
      "\264\362\375\305",
      "\363\366\305",
    #endif
    seqsize(5,0) - seqsize(3,0)
  },
  {
    #ifdef SCPACK
      "xchg!sleq!swap.alt!and!pop.alt!jzer %1!",
      "sgeq!pop.alt!and!jzer %1!",
    #else
      "\264\363\375\305",
      "\362\366\305",
    #endif
    seqsize(5,0) - seqsize(3,0)
  },
  {
    #ifdef SCPACK
      "xchg!sgrtr!jzer %1!;$exp!",
      "jsgeq %1!;$exp!",
    #else
      "\264\365\266\261",
      "j\302\254\261",
    #endif
    seqsize(3,1) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "xchg!sless!jzer %1!;$exp!",
      "jsleq %1!;$exp!",
    #else
      "\264\360\266\261",
      "j\303\254\261",
    #endif
    seqsize(3,1) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "xchg!sgeq!jzer %1!;$exp!",
      "jsgrtr %1!;$exp!",
    #else
      "\264\362\266\261",
      "j\342r\261",
    #endif
    seqsize(3,1) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "xchg!sleq!jzer %1!;$exp!",
      "jsless %1!;$exp!",
    #else
      "\264\363\266\261",
      "j\340\261",
    #endif
    seqsize(3,1) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "xchg!sgrtr!;$exp!",
      "sless!;$exp!",
    #else
      "\264\365\244",
      "\360\244",
    #endif
    seqsize(2,0) - seqsize(1,0)
  },
  {
    #ifdef SCPACK
      "xchg!sless!;$exp!",
      "sgrtr!;$exp!",
    #else
      "\264\360\244",
      "\365\244",
    #endif
    seqsize(2,0) - seqsize(1,0)
  },
  {
    #ifdef SCPACK
      "xchg!sgeq!;$exp!",
      "sleq!;$exp!",
    #else
      "\264\362\244",
      "\363\244",
    #endif
    seqsize(2,0) - seqsize(1,0)
  },
  {
    #ifdef SCPACK
      "xchg!sleq!;$exp!",
      "sgeq!;$exp!",
    #else
      "\264\363\244",
      "\362\244",
    #endif
    seqsize(2,0) - seqsize(1,0)
  },
  /* The entry to chained operators is also opt to optimization
   *    load.s.pri n1           load.s.pri n2
   *    load.s.alt n2           load.s.alt n1
   *    xchg                    -
   *    --------------------------------------
   *    load.s.pri n1           load.pri n2
   *    load.alt n2             load.s.alt n1
   *    xchg                    -
   *    --------------------------------------
   *    load.s.pri n1           const.pri n2
   *    const.alt n2            load.s.alt n1
   *    xchg                    -
   *    --------------------------------------
   * and all permutations...
   */
  {
    #ifdef SCPACK
      "load.s.pri %1!load.s.alt %2!xchg!",
      "load.s.pri %2!load.s.alt %1!",
    #else
      "\325\224\364",
      "\245\224\246",
    #endif
    seqsize(3,2) - seqsize(2,2)
  },
  {
    #ifdef SCPACK
      "load.s.pri %1!load.alt %2!xchg!",
      "load.pri %2!load.s.alt %1!",
    #else
      "\325\213\364",
      "\317\224\246",
    #endif
    seqsize(3,2) - seqsize(2,2)
  },
  {
    #ifdef SCPACK
      "load.s.pri %1!const.alt %2!xchg!",
      "const.pri %2!load.s.alt %1!",
    #else
      "\325\237\364",
      "\355\224\246",
    #endif
    seqsize(3,2) - seqsize(2,2)
  },
  {
    #ifdef SCPACK
      "load.pri %1!load.s.alt %2!xchg!",
      "load.s.pri %2!load.alt %1!",
    #else
      "\315\224\364",
      "\245\213\246",
    #endif
    seqsize(3,2) - seqsize(2,2)
  },
  {
    #ifdef SCPACK
      "load.pri %1!load.alt %2!xchg!",
      "load.pri %2!load.alt %1!",
    #else
      "\315\213\364",
      "\317\213\246",
    #endif
    seqsize(3,2) - seqsize(2,2)
  },
  {
    #ifdef SCPACK
      "load.pri %1!const.alt %2!xchg!",
      "const.pri %2!load.alt %1!",
    #else
      "\315\237\364",
      "\355\213\246",
    #endif
    seqsize(3,2) - seqsize(2,2)
  },
  {
    #ifdef SCPACK
      "const.pri %1!load.s.alt %2!xchg!",
      "load.s.pri %2!const.alt %1!",
    #else
      "\316\224\364",
      "\245\361",
    #endif
    seqsize(3,2) - seqsize(2,2)
  },
  {
    #ifdef SCPACK
      "const.pri %1!load.alt %2!xchg!",
      "load.pri %2!const.alt %1!",
    #else
      "\316\213\364",
      "\317\361",
    #endif
    seqsize(3,2) - seqsize(2,2)
  },
  /* Array indexing can merit from special instructions.
   * Simple indexed array lookup can be optimized quite
   * a bit.
   *    addr.pri n1             addr.alt n1
   *    push.pri                load.s.pri n2
   *    load.s.pri n2           bounds n3
   *    bounds n3               lidx.b n4
   *    shl.c.pri n4            -
   *    pop.alt                 -
   *    add                     -
   *    load.i                  -
   *
   * And to prepare for storing a value in an array
   *    addr.pri n1             addr.alt n1
   *    push.pri                load.s.pri n2
   *    load.s.pri n2           bounds n3
   *    bounds n3               idxaddr.b n4
   *    shl.c.pri n4            -
   *    pop.alt                 -
   *    add                     -
   *
   * Notes (additional cases):
   * 1. instruction addr.pri can also be const.pri (for
   *    global arrays)
   * 2. the bounds instruction can be absent
   * 3. when "n4" (the shift value) is the 2 (with 32-bit cels), use the
   *    even more optimal instructions LIDX and IDDXADDR
   *
   * If the array index is more complex, one can only optimize
   * the last four instructions:
   *    shl.c.pri n1            pop.alt
   *    pop.alt                 lidx.b n1
   *    add                     -
   *    loadi                   -
   *    --------------------------------------
   *    shl.c.pri n1            pop.alt
   *    pop.alt                 idxaddr.b n1
   *    add                     -
   */
#if !defined BIT16
  /* loading from array, "cell" shifted */
  {
    #ifdef SCPACK
      "addr.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri 2!pop.alt!add!load.i!",
      "addr.alt %1!load.s.pri %2!bounds %3!lidx!",
    #else
      "\334\300\343\370",
      "\252\335\336!",
    #endif
    seqsize(8,4) - seqsize(4,3)
  },
  {
    #ifdef SCPACK
      "const.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri 2!pop.alt!add!load.i!",
      "const.alt %1!load.s.pri %2!bounds %3!lidx!",
    #else
      "\333\300\343\370",
      "\237\335\336!",
    #endif
    seqsize(8,4) - seqsize(4,3)
  },
  {
    #ifdef SCPACK
      "addr.pri %1!push.pri!load.s.pri %2!shl.c.pri 2!pop.alt!add!load.i!",
      "addr.alt %1!load.s.pri %2!lidx!",
    #else
      "\334\343\370",
      "\252\307\336!",
    #endif
    seqsize(7,3) - seqsize(3,2)
  },
  {
    #ifdef SCPACK
      "const.pri %1!push.pri!load.s.pri %2!shl.c.pri 2!pop.alt!add!load.i!",
      "const.alt %1!load.s.pri %2!lidx!",
    #else
      "\333\343\370",
      "\237\307\336!",
    #endif
    seqsize(7,3) - seqsize(3,2)
  },
#endif
  /* loading from array, not "cell" shifted */
  {
    #ifdef SCPACK
      "addr.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri %4!pop.alt!add!load.i!",
      "addr.alt %1!load.s.pri %2!bounds %3!lidx.b %4!",
    #else
      "\334\300\310\367\370",
      "\252\335\336\345\367",
    #endif
    seqsize(8,4) - seqsize(4,4)
  },
  {
    #ifdef SCPACK
      "const.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri %4!pop.alt!add!load.i!",
      "const.alt %1!load.s.pri %2!bounds %3!lidx.b %4!",
    #else
      "\333\300\310\367\370",
      "\237\335\336\345\367",
    #endif
    seqsize(8,4) - seqsize(4,4)
  },
  {
    #ifdef SCPACK
      "addr.pri %1!push.pri!load.s.pri %2!shl.c.pri %3!pop.alt!add!load.i!",
      "addr.alt %1!load.s.pri %2!lidx.b %3!",
    #else
      "\334\310\257\370",
      "\252\307\336\345\257",
    #endif
    seqsize(7,3) - seqsize(3,3)
  },
  {
    #ifdef SCPACK
      "const.pri %1!push.pri!load.s.pri %2!shl.c.pri %3!pop.alt!add!load.i!",
      "const.alt %1!load.s.pri %2!lidx.b %3!",
    #else
      "\333\310\257\370",
      "\237\307\336\345\257",
    #endif
    seqsize(7,3) - seqsize(3,3)
  },
#if !defined BIT16
  /* array index calculation for storing a value, "cell" aligned */
  {
    #ifdef SCPACK
      "addr.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri 2!pop.alt!add!",
      "addr.alt %1!load.s.pri %2!bounds %3!idxaddr!",
    #else
      "\334\300\343\275",
      "\252\335\332!",
    #endif
    seqsize(7,4) - seqsize(4,3)
  },
  {
    #ifdef SCPACK
      "const.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri 2!pop.alt!add!",
      "const.alt %1!load.s.pri %2!bounds %3!idxaddr!",
    #else
      "\333\300\343\275",
      "\237\335\332!",
    #endif
    seqsize(7,4) - seqsize(4,3)
  },
  {
    #ifdef SCPACK
      "addr.pri %1!push.pri!load.s.pri %2!shl.c.pri 2!pop.alt!add!",
      "addr.alt %1!load.s.pri %2!idxaddr!",
    #else
      "\334\343\275",
      "\252\307\332!",
    #endif
    seqsize(6,3) - seqsize(3,2)
  },
  {
    #ifdef SCPACK
      "const.pri %1!push.pri!load.s.pri %2!shl.c.pri 2!pop.alt!add!",
      "const.alt %1!load.s.pri %2!idxaddr!",
    #else
      "\333\343\275",
      "\237\307\332!",
    #endif
    seqsize(6,3) - seqsize(3,2)
  },
#endif
  /* array index calculation for storing a value, not "cell" packed */
  {
    #ifdef SCPACK
      "addr.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri %4!pop.alt!add!",
      "addr.alt %1!load.s.pri %2!bounds %3!idxaddr.b %4!",
    #else
      "\334\300\310\367\275",
      "\252\335\332\345\367",
    #endif
    seqsize(7,4) - seqsize(4,4)
  },
  {
    #ifdef SCPACK
      "const.pri %1!push.pri!load.s.pri %2!bounds %3!shl.c.pri %4!pop.alt!add!",
      "const.alt %1!load.s.pri %2!bounds %3!idxaddr.b %4!",
    #else
      "\333\300\310\367\275",
      "\237\335\332\345\367",
    #endif
    seqsize(7,4) - seqsize(4,4)
  },
  {
    #ifdef SCPACK
      "addr.pri %1!push.pri!load.s.pri %2!shl.c.pri %3!pop.alt!add!",
      "addr.alt %1!load.s.pri %2!idxaddr.b %3!",
    #else
      "\334\310\257\275",
      "\252\307\332\345\257",
    #endif
    seqsize(6,3) - seqsize(3,3)
  },
  {
    #ifdef SCPACK
      "const.pri %1!push.pri!load.s.pri %2!shl.c.pri %3!pop.alt!add!",
      "const.alt %1!load.s.pri %2!idxaddr.b %3!",
    #else
      "\333\310\257\275",
      "\237\307\332\345\257",
    #endif
    seqsize(6,3) - seqsize(3,3)
  },
#if !defined BIT16
  /* the shorter array indexing sequences, see above for comments */
  {
    #ifdef SCPACK
      "shl.c.pri 2!pop.alt!add!loadi!",
      "pop.alt!lidx!",
    #else
      "\343\327\320",
      "\234\336!",
    #endif
    seqsize(4,1) - seqsize(2,0)
  },
  {
    #ifdef SCPACK
      "shl.c.pri 2!pop.alt!add!",
      "pop.alt!idxaddr!",
    #else
      "\343\275",
      "\234\332!",
    #endif
    seqsize(3,1) - seqsize(2,0)
  },
#endif
  {
    #ifdef SCPACK
      "shl.c.pri %1!pop.alt!add!loadi!",
      "pop.alt!lidx.b %1!",
    #else
      "\276\223\327\320",
      "\234\336\345\205",
    #endif
    seqsize(4,1) - seqsize(2,1)
  },
  {
    #ifdef SCPACK
      "shl.c.pri %1!pop.alt!add!",
      "pop.alt!idxaddr.b %1!",
    #else
      "\276\223\275",
      "\234\332\345\205",
    #endif
    seqsize(3,1) - seqsize(2,1)
  },
  /* For packed arrays, there is another case (packed arrays
   * do not take advantage of the LIDX or IDXADDR instructions).
   *    addr.pri n1             addr.alt n1
   *    push.pri                load.s.pri n2
   *    load.s.pri n2           bounds n3
   *    bounds n3               -
   *    pop.alt                 -
   *
   * Notes (additional cases):
   * 1. instruction addr.pri can also be const.pri (for
   *    global arrays)
   * 2. the bounds instruction can be absent, but that
   *    case is already handled (see #1#)
   */
  {
    #ifdef SCPACK
      "addr.pri %1!push.pri!load.s.pri %2!bounds %3!pop.alt!",
      "addr.alt %1!load.s.pri %2!bounds %3!",
    #else
      "\334\300\234",
      "\252\335",
    #endif
    seqsize(5,3) - seqsize(3,3)
  },
  {
    #ifdef SCPACK
      "const.pri %1!push.pri!load.s.pri %2!bounds %3!pop.alt!",
      "const.alt %1!load.s.pri %2!bounds %3!",
    #else
      "\333\300\234",
      "\237\335",
    #endif
    seqsize(5,3) - seqsize(3,3)
  },
  /* Declaration of simple variables often follows the sequence:
   *    ;$lcl <name> <stk>      ;$lcl <name> <stk>
   *    stack -4                push.c <constval>
   *    const.pri <constval>    ;$exp
   *    stor.s.pri <stk>        -
   *    ;$exp                   -
   */
  {
    #ifdef SCPACK
      ";$lcl %1 %2!stack -4!const.pri %3!stor.s.pri %2!;$exp!",
      ";$lcl %1 %2!push.c %3!;$exp!",
    #else
      "\231lcl\204\216\227ack -\331\237\203\257\227or\220\226\244",
      "\231lcl\204\216\321\257\244",
    #endif
    seqsize(3,3) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      ";$lcl %1 %2!stack -4!zero.pri!stor.s.pri %2!;$exp!",
      ";$lcl %1 %2!push.c 0!;$exp!",
    #else
      "\231lcl\204\216\227ack -\331\353\227or\220\226\244",
      "\231lcl\204\216\321 0!\244",
    #endif
    seqsize(3,2) - seqsize(1,1)
  },
  /* During a calculation, the intermediate result must sometimes
   * be moved from PRI to ALT, like in:
   *    push.pri                move.alt
   *    load.s.pri n1           load.s.pri n1
   *    pop.alt                 -
   *
   * The above also accurs for "load.pri" and for "const.pri",
   * so add another two cases.
   */
  {
    #ifdef SCPACK
      "push.pri!load.s.pri %1!pop.alt!",
      "move.alt!load.s.pri %1!",
    #else
      "\240\325\234",
      "\351\217\325",
    #endif
    seqsize(3,1) - seqsize(2,1)
  },
  {
    #ifdef SCPACK
      "push.pri!load.pri %1!pop.alt!",
      "move.alt!load.pri %1!",
    #else
      "\240\315\234",
      "\351\217\315",
    #endif
    seqsize(3,1) - seqsize(2,1)
  },
  {
    #ifdef SCPACK
      "push.pri!const.pri %1!pop.alt!",
      "move.alt!const.pri %1!",
    #else
      "\240\316\234",
      "\351\217\316",
    #endif
    seqsize(3,1) - seqsize(2,1)
  },
  {
    #ifdef SCPACK
      "push.pri!zero.pri!pop.alt!",
      "move.alt!zero.pri!",
    #else
      "\240\353\234",
      "\351\217\353",
    #endif
    seqsize(3,0) - seqsize(2,0)
  },
  /* saving PRI and then loading from its address
   * occurs when indexing a multi-dimensional array
   */
  {
    #ifdef SCPACK
      "push.pri!load.i!pop.alt!",
      "move.alt!load.i!",
    #else
      "\240\213\341\234",
      "\351\217\213\341",
    #endif
    seqsize(3,0) - seqsize(2,0)
  },
  /* An even simpler PUSH/POP optimization (occurs in
   * switch statements):
   *    push.pri                move.alt
   *    pop.alt                 -
   */
  {
    #ifdef SCPACK
      "push.pri!pop.alt!",
      "move.alt!",
    #else
      "\240\234",
      "\351\217",
    #endif
    seqsize(2,0) - seqsize(1,0)
  },
  /* And what to think of this PUSH/POP sequence, which occurs
   * due to the support for user-defined assignment operator):
   *    push.alt                -
   *    pop.alt                 -
   */
//???
//{
//  #ifdef SCPACK
//    "push.alt!pop.alt!",
//    ";$",     /* SCPACK cannot handle empty strings */
//  #else
//    "\225\237",
//    "\353",
//  #endif
//  seqsize(2,0) - seqsize(0,0)
//},
  /* Functions with many parameters with the same default
   * value have sequences like:
   *    push.c n1               const.pri n1
   *    ;$par                   push.r.pri n2   ; where n2 is the number of pushes
   *    push.c n1               ;$par
   *    ;$par                   -
   *    push.c n1               -
   *    ;$par                   -
   *    etc.                    etc.
   * The shortest matched sequence is 3, because a sequence of two can also be
   * optimized as two "push.c n1" instructions.
   * => this optimization does not work, because the argument re-ordering in
   *    a function call causes each argument to be optimized individually
   */
//{
//  #ifdef SCPACK
//    "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!",
//    "const.pri %1!push.r.pri 5!;$par!",
//  #else
//    "\327\327\254",
//    "\352\221.r\2745!",
//  #endif
//  seqsize(10,5) - seqsize(2,2)
//},
//{
//  #ifdef SCPACK
//    "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.r.pri 4!;$par!",
//  #else
//    "\327\327",
//    "\352\221.r\274\326",
//  #endif
//  seqsize(8,4) - seqsize(2,2)
//},
//{
//  #ifdef SCPACK
//    "const.pri %1!push.pri!;$par!const.pri %1!push.pri!;$par!const.pri %1!push.pri!;$par!",
//    "const.pri %1!push.r.pri 3!;$par!",
//  #else
//    "\327\254",
//    "\352\221.r\274\247",
//  #endif
//  seqsize(6,3) - seqsize(2,2)
//},
  /* User-defined operators first load the operands into registers and
   * then have them pushed onto the stack. This can give rise to sequences
   * like:
   *    const.pri n1            push.c n1
   *    const.alt n2            push.c n2
   *    push.pri                -
   *    push.alt                -
   * A similar sequence occurs with the two PUSH.pri/alt instructions inverted.
   * The first, second, or both CONST.pri/alt instructions can also be
   * LOAD.pri/alt.
   * This gives 2 x 4 cases.
   */
  {
    #ifdef SCPACK
      "const.pri %1!const.alt %2!push.pri!push.alt!",
      "push.c %1!push.c %2!",
    #else
      "\316\237\311\240\352",
      "\321\205\321\216",
    #endif
    seqsize(4,2) - seqsize(2,2)
  },
  {
    #ifdef SCPACK
      "const.pri %1!const.alt %2!push.alt!push.pri!",
      "push.c %2!push.c %1!",
    #else
      "\316\237\311\352\240",
      "\321\216\321\205",
    #endif
    seqsize(4,2) - seqsize(2,2)
  },
  {
    #ifdef SCPACK
      "const.pri %1!load.alt %2!push.pri!push.alt!",
      "push.c %1!push %2!",
    #else
      "\316\213\311\240\352",
      "\321\205\222\216",
    #endif
    seqsize(4,2) - seqsize(2,2)
  },
  {
    #ifdef SCPACK
      "const.pri %1!load.alt %2!push.alt!push.pri!",
      "push %2!push.c %1!",
    #else
      "\316\213\311\352\240",
      "\222\216\321\205",
    #endif
    seqsize(4,2) - seqsize(2,2)
  },
  {
    #ifdef SCPACK
      "load.pri %1!const.alt %2!push.pri!push.alt!",
      "push %1!push.c %2!",
    #else
      "\315\237\311\240\352",
      "\222\205\321\216",
    #endif
    seqsize(4,2) - seqsize(2,2)
  },
  {
    #ifdef SCPACK
      "load.pri %1!const.alt %2!push.alt!push.pri!",
      "push.c %2!push %1!",
    #else
      "\315\237\311\352\240",
      "\321\216\222\205",
    #endif
    seqsize(4,2) - seqsize(2,2)
  },
  {
    #ifdef SCPACK
      "load.pri %1!load.alt %2!push.pri!push.alt!",
      "push %1!push %2!",
    #else
      "\315\213\311\240\352",
      "\222\205\222\216",
    #endif
    seqsize(4,2) - seqsize(2,2)
  },
  {
    #ifdef SCPACK
      "load.pri %1!load.alt %2!push.alt!push.pri!",
      "push %2!push %1!",
    #else
      "\315\213\311\352\240",
      "\222\216\222\205",
    #endif
    seqsize(4,2) - seqsize(2,2)
  },
  /* Function calls (parameters are passed on the stack)
   *    load.s.pri n1           push.s n1
   *    push.pri                -
   *    --------------------------------------
   *    load.pri n1             push n1
   *    push.pri                -
   *    --------------------------------------
   *    const.pri n1            push.c n1
   *    push.pri                -
   *    --------------------------------------
   *    zero.pri                push.c 0
   *    push.pri                -
   *    --------------------------------------
   *    addr.pri n1             pushaddr n1
   *    push.pri                -
   *
   * However, PRI must not be needed after this instruction
   * if this shortcut is used. Check for the ;$par comment.
   */
  {
    #ifdef SCPACK
      "load.s.pri %1!push.pri!;$par!",
      "push.s %1!;$par!",
    #else
      "\224\255\347",
      "\222\220\205\347",
    #endif
    seqsize(2,1) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "load.pri %1!push.pri!;$par!",
      "push %1!;$par!",
    #else
      "\213\255\347",
      "\222\205\347",
    #endif
    seqsize(2,1) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "const.pri %1!push.pri!;$par!",
      "push.c %1!;$par!",
    #else
      "\237\255\347",
      "\321\205\347",
    #endif
    seqsize(2,1) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "zero.pri!push.pri!;$par!",
      "push.c 0!;$par!",
    #else
      "\353\240\347",
      "\321 0!\347",
    #endif
    seqsize(2,0) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "addr.pri %1!push.pri!;$par!",
      "pushaddr %1!;$par!",
    #else
      "\252\255\347",
      "\222\252\205\347",
    #endif
    seqsize(2,1) - seqsize(1,1)
  },
  /* References with a default value generate new cells on the heap
   * dynamically. That code often ends with:
   *    move.pri                push.alt
   *    push.pri                -
   */
  {
    #ifdef SCPACK
      "move.pri!push.pri!",
      "push.alt!",
    #else
      "\351\230\240",
      "\352",
    #endif
    seqsize(2,0) - seqsize(1,0)
  },
  /* Simple arithmetic operations on constants. Noteworthy is the
   * subtraction of a constant, since it is converted to the addition
   * of the inverse value.
   *    const.alt n1            add.c n1
   *    add                     -
   *    --------------------------------------
   *    const.alt n1            add.c -n1
   *    sub                     -
   *    --------------------------------------
   *    const.alt n1            smul.c n1
   *    smul                    -
   *    --------------------------------------
   *    const.alt n1            eq.c.pri n1
   *    eq                      -
   */
  {
    #ifdef SCPACK
      "const.alt %1!add!",
      "add.c %1!",
    #else
      "\361\270",
      "\376\205",
    #endif
    seqsize(2,1) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "const.alt %1!sub!",
      "add.c -%1!",
    #else
      "\361sub!",
      "\376 -%1!",
    #endif
    seqsize(2,1) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "const.alt %1!smul!",
      "smul.c %1!",
    #else
      "\361smul!",
      "smu\271\205",
    #endif
    seqsize(2,1) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "const.alt %1!eq!",
      "eq.c.pri %1!",
    #else
      "\361\265",
      "\254\247\223",
    #endif
    seqsize(2,1) - seqsize(1,1)
  },
  /* Some operations use the alternative subtraction operation --these
   * can also be optimized.
   *    const.pri n1            load.s.pri n2
   *    load.s.alt n2           add.c -n1
   *    sub.alt                 -
   *    --------------------------------------
   *    const.pri n1            load.pri n2
   *    load.alt n2             add.c -n1
   *    sub.alt                 -
   */
  {
    #ifdef SCPACK
      "const.pri %1!load.s.alt %2!sub.alt!",
      "load.s.pri %2!add.c -%1!",
    #else
      "\316\224\311sub\217",
      "\245\376 -%1!",
    #endif
    seqsize(3,2) - seqsize(2,2)
  },
  {
    #ifdef SCPACK
      "const.pri %1!load.alt %2!sub.alt!",
      "load.pri %2!add.c -%1!",
    #else
      "\316\213\311sub\217",
      "\317\376 -%1!",
    #endif
    seqsize(3,2) - seqsize(2,2)
  },
  /* With arrays indexed with constants that come from enumerations, it happens
   * multiple add.c opcodes follow in sequence.
   *    add.c n1                add.c n1+n2
   *    add.c n2                -
   */
  {
    #ifdef SCPACK
      "add.c %1!add.c %2!",
      "add.c %1+%2!",
    #else
      "\376\205\376\216",
      "\376\204+%\214",
    #endif
    seqsize(2,2) - seqsize(1,1)
  },
  /* Compare and jump
   *    eq                      jneq n1
   *    jzer n1                 -
   *    --------------------------------------
   *    eq                      jeq n1
   *    jnz n1                  -
   *    --------------------------------------
   *    neq                     jeq n1
   *    jzer n1                 -
   *    --------------------------------------
   *    neq                     jneq n1
   *    jnz n1                  -
   * Compares followed by jzer occur much more
   * often than compares followed with jnz. So we
   * take the easy route here.
   *    less                    jgeq n1
   *    jzer n1                 -
   *    --------------------------------------
   *    leq                     jgrtr n1
   *    jzer n1                 -
   *    --------------------------------------
   *    grtr                    jleq n1
   *    jzer n1                 -
   *    --------------------------------------
   *    geq                     jless n1
   *    jzer n1                 -
   *    --------------------------------------
   *    sless                   jsgeq n1
   *    jzer n1                 -
   *    --------------------------------------
   *    sleq                    jsgrtr n1
   *    jzer n1                 -
   *    --------------------------------------
   *    sgrtr                   jsleq n1
   *    jzer n1                 -
   *    --------------------------------------
   *    sgeq                    jsless n1
   *    jzer n1                 -
   */
  {
    #ifdef SCPACK
      "eq!jzer %1!",
      "jneq %1!",
    #else
      "\265\305",
      "jn\326",
    #endif
    seqsize(2,1) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "eq!jnz %1!",
      "jeq %1!",
    #else
      "\265jnz\205",
      "j\326",
    #endif
    seqsize(2,1) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "neq!jzer %1!",
      "jeq %1!",
    #else
      "n\265\305",
      "j\326",
    #endif
    seqsize(2,1) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "neq!jnz %1!",
      "jneq %1!",
    #else
      "n\265jnz\205",
      "jn\326",
    #endif
    seqsize(2,1) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "less!jzer %1!",
      "jgeq %1!",
    #else
      "l\323!\305",
      "jg\326",
    #endif
    seqsize(2,1) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "leq!jzer %1!",
      "jgrtr %1!",
    #else
      "l\265\305",
      "jg\324r\205",
    #endif
    seqsize(2,1) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "grtr!jzer %1!",
      "jleq %1!",
    #else
      "g\324\306\305",
      "jl\326",
    #endif
    seqsize(2,1) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "geq!jzer %1!",
      "jless %1!",
    #else
      "g\265\305",
      "jl\323\205",
    #endif
    seqsize(2,1) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "sless!jzer %1!",
      "jsgeq %1!",
    #else
      "\360\305",
      "j\302\326",
    #endif
    seqsize(2,1) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "sleq!jzer %1!",
      "jsgrtr %1!",
    #else
      "\363\305",
      "j\342r\205",
    #endif
    seqsize(2,1) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "sgrtr!jzer %1!",
      "jsleq %1!",
    #else
      "\365\305",
      "j\303\326",
    #endif
    seqsize(2,1) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "sgeq!jzer %1!",
      "jsless %1!",
    #else
      "\362\305",
      "j\340\205",
    #endif
    seqsize(2,1) - seqsize(1,1)
  },
  /* Test for zero (common case, especially for strings)
   * E.g. the test expression of: "for (i=0; str{i}!=0; ++i)"
   *
   *    zero.alt                jzer n1
   *    jeq n1                  -
   *    --------------------------------------
   *    zero.alt                jnz n1
   *    jneq n1                 -
   */
  {
    #ifdef SCPACK
      "zero.alt!jeq %1!",
      "jzer %1!",
    #else
      "\314\217j\326",
      "\305",
    #endif
    seqsize(2,1) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "zero.alt!jneq %1!",
      "jnz %1!",
    #else
      "\314\217jn\326",
      "jnz\205",
    #endif
    seqsize(2,1) - seqsize(1,1)
  },
  /* Incrementing and decrementing leaves a value in
   * in PRI which may not be used (for example, as the
   * third expression in a "for" loop).
   *    inc n1                  inc n1  ; ++n
   *    load.pri n1             ;$exp
   *    ;$exp                   -
   *    --------------------------------------
   *    load.pri n1             inc n1  ; n++, e.g. "for (n=0; n<10; n++)"
   *    inc n1                  ;$exp
   *    ;$exp                   -
   * Plus the varieties for stack relative increments
   * and decrements.
   */
  {
    #ifdef SCPACK
      "inc %1!load.pri %1!;$exp!",
      "inc %1!;$exp!",
    #else
      "\373c\205\315\244",
      "\373c\261",
    #endif
    seqsize(2,2) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "load.pri %1!inc %1!;$exp!",
      "inc %1!;$exp!",
    #else
      "\315\373c\261",
      "\373c\261",
    #endif
    seqsize(2,2) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "inc.s %1!load.s.pri %1!;$exp!",
      "inc.s %1!;$exp!",
    #else
      "\373\354\205\325\244",
      "\373\354\261",
    #endif
    seqsize(2,2) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "load.s.pri %1!inc.s %1!;$exp!",
      "inc.s %1!;$exp!",
    #else
      "\325\373\354\261",
      "\373\354\261",
    #endif
    seqsize(2,2) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "dec %1!load.pri %1!;$exp!",
      "dec %1!;$exp!",
    #else
      "\371c\205\315\244",
      "\371c\261",
    #endif
    seqsize(2,2) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "load.pri %1!dec %1!;$exp!",
      "dec %1!;$exp!",
    #else
      "\315\371c\261",
      "\371c\261",
    #endif
    seqsize(2,2) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "dec.s %1!load.s.pri %1!;$exp!",
      "dec.s %1!;$exp!",
    #else
      "\371\354\205\325\244",
      "\371\354\261",
    #endif
    seqsize(2,2) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "load.s.pri %1!dec.s %1!;$exp!",
      "dec.s %1!;$exp!",
    #else
      "\325\371\354\261",
      "\371\354\261",
    #endif
    seqsize(2,2) - seqsize(1,1)
  },
  /* ??? the same (increments and decrements) for references */
  /* Loading the constant zero has a special opcode.
   * When storing zero in memory, the value of PRI must not be later on.
   *    const.pri 0             zero n1
   *    stor.pri n1             ;$exp
   *    ;$exp                   -
   *    --------------------------------------
   *    const.pri 0             zero.s n1
   *    stor.s.pri n1           ;$exp
   *    ;$exp                   -
   *    --------------------------------------
   *    zero.pri                zero n1
   *    stor.pri n1             ;$exp
   *    ;$exp                   -
   *    --------------------------------------
   *    zero.pri                zero.s n1
   *    stor.s.pri n1           ;$exp
   *    ;$exp                   -
   *    --------------------------------------
   *    const.pri 0             zero.pri
   *    --------------------------------------
   *    const.alt 0             zero.alt
   * The last two alternatives save more memory than they save
   * time, but anyway...
   */
  {
    #ifdef SCPACK
      "const.pri 0!stor.pri %1!;$exp!",
      "zero %1!;$exp!",
    #else
      "\237\203 0!\227or\223\244",
      "\314\261",
    #endif
    seqsize(2,2) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "const.pri 0!stor.s.pri %1!;$exp!",
      "zero.s %1!;$exp!",
    #else
      "\237\203 0!\227or\220\223\244",
      "\314\220\261",
    #endif
    seqsize(2,2) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "zero.pri!stor.pri %1!;$exp!",
      "zero %1!;$exp!",
    #else
      "\353\227or\223\244",
      "\314\261",
    #endif
    seqsize(2,1) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "zero.pri!stor.s.pri %1!;$exp!",
      "zero.s %1!;$exp!",
    #else
      "\353\227or\220\223\244",
      "\314\220\261",
    #endif
    seqsize(2,1) - seqsize(1,1)
  },
  {
    #ifdef SCPACK
      "const.pri 0!",
      "zero.pri!",
    #else
      "\237\203 0!",
      "\353",
    #endif
    seqsize(1,1) - seqsize(1,0)
  },
  {
    #ifdef SCPACK
      "const.alt 0!",
      "zero.alt!",
    #else
      "\237\211 0!",
      "\314\217",
    #endif
    seqsize(1,1) - seqsize(1,0)
  },
  /* ----- */
  { NULL, NULL, 0 }
};
