15-5-83 EGK
authorkeie <none@none>
Mon, 7 Jan 1985 13:51:36 +0000 (13:51 +0000)
committerkeie <none@none>
Mon, 7 Jan 1985 13:51:36 +0000 (13:51 +0000)
                The coercion from rm1 to register contained
                allocate(%[1],GENREG).
                The %[1] here is incorrect and has been removed.
16-5-83         EGK
                The word before the movb was cleared by a xor.
                Now we clear the upper byte after the movb.
                This allows the %[1] to be added to the allocate.

mach/i86/cg/table [new file with mode: 0644]

diff --git a/mach/i86/cg/table b/mach/i86/cg/table
new file mode 100644 (file)
index 0000000..482fd60
--- /dev/null
@@ -0,0 +1,2327 @@
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+#define SL 4
+#define SSL "4"
+
+/********************************************************
+ * Back end tables for Intel 8086                      *
+ * Author : Ed Keizer                                  *
+ *                                                     *
+ * wordsize = 2 bytes, pointersize = 2 bytes.          *
+ *                                                     *
+ * Register bp is used as LB, sp is used for SP.       *
+ * Some global variables are used:                     *
+ * - .reghp    : the heap pointer                      *
+ * - .ignmask  : trap ignore mask                      *
+ * - .trppc    : address of user defined trap handler  *
+ *                                                     *
+ * Floating point arithmetic and constants are not     *
+ * implemented.
+ *                                                     *
+ ********************************************************/
+
+/* #define DEEPER      1
+/*     When DEEPER is disabled, the table contains some
+       heuristics based on the assumption that look-ahead will
+       be minimal.
+       Example: Addition of constants to registers will no take
+       place via ax, but in an address register, in the rules for ads.
+       Thereby assuming that the resulting register will be used
+       to access memory.
+       When DEEPER is enabled these heuristics are disabled
+       thereby allowing the code-generator too see for itself
+       which code will be shorter.
+*/
+
+#define SPEED          1
+/* This definition produces a slightly different table,
+   producing slightly less efficient code with greater speed
+*/
+
+#ifdef SPEED
+
+#define NO     nocoercions :
+
+#else
+
+#define NO
+
+#endif
+
+EM_WSIZE=2
+EM_PSIZE=2
+EM_BSIZE=SL
+
+SIZEFACTOR=5
+
+REGISTERS:
+
+al     = ("al", 2), REG1, ACC1.
+ah     = ("ah", 2), REG1.
+bl     = ("bl", 2), REG1.
+bh     = ("bh", 2), REG1.
+cl     = ("cl", 2), REG1, SHIFT_CREG.
+ch     = ("ch", 2), REG1.
+dl     = ("dl", 2), REG1.
+dh     = ("dh", 2), REG1.
+ax     = ("ax", 2, al, ah), REG, GENREG, ACC.
+bx     = ("bx", 2, bl, bh), REG, GENREG, BREG, BXREG, ADDREG.
+cx     = ("cx", 2, cl, ch), REG, GENREG, CXREG, SHIFT_CREG.
+dx     = ("dx", 2, dl, dh), REG, GENREG, DXREG.
+si     = ("si", 2), REG, IREG, SIREG, ADDREG.
+di     = ("di", 2), REG, IREG, DIREG, ADDREG.
+bp     = ("bp", 2), BREG.
+
+TOKENS:
+
+/********************************
+ * Types on the EM-machine     *
+ ********************************/
+
+ANYCON         = { INT val ; }                 2 cost=(2, 1) "%[val]"
+ADDR_EXTERN    = { STRING off ; }              2 cost=(2, 1) "%[off]"
+EXTERN1        = { STRING off ; }              2 cost=(2,12) "(%[off])"
+EXTERN2        = { STRING off ; }              2 cost=(2,12) "(%[off])"
+ADDR_LOCAL     = { INT ind ; }                 2 cost=(1, 9) "%[ind](bp)"
+LOCAL2         = { INT ind, size ; }           2 cost=(1,15) "%[ind](bp)"
+LOCAL1         = { INT ind, size ; }           2 cost=(1,15) "%[ind](bp)"
+
+
+/********************************************************
+ * Now mostly addressing modes of target machine       *
+ ********************************************************/
+
+
+/*****************************************
+ * 'Half modes' consisting of summations *
+ * of constant and or register(s)       *
+ *****************************************/
+
+reg_off    = { REGISTER reg; STRING off; } 2 cost=(1, 9) "%[off](%[reg])"
+bpreg_off  = { REGISTER reg; INT ind; }    2 cost=(1,11) "%[ind](bp)(%[reg])"
+
+/**************************************************
+ * Indirect through registers and the modes above *
+ * Token names ending on digits are indirect     *
+ **************************************************/
+
+
+ind_reg2       = { REGISTER reg; }             2 cost=(0,11) "(%[reg])"
+ind_regoff2    = { REGISTER reg; STRING off; } 2 cost=(1,15) "%[off](%[reg])"
+ind_bpregoff2  = { REGISTER reg; INT ind; }    2 cost=(1,18)
+                                                         "%[ind](bp)(%[reg])"
+
+ind_reg1       = { REGISTER reg; }             2 cost=(0,11) "(%[reg])"
+ind_regoff1    = { REGISTER reg; STRING off; } 2 cost=(1,15) "%[off](%[reg])"
+ind_bpregoff1  = { REGISTER reg; INT ind; }    2 cost=(1,18)
+                                                         "%[ind](bp)(%[reg])"
+
+TOKENEXPRESSIONS:
+
+/* SCRATCH REGISTERS */
+X_ACC          = ACC*SCRATCH
+X_ACC1         = ACC1*SCRATCH
+X_REG          = REG*SCRATCH
+X_BXREG        = BXREG*SCRATCH
+X_DXREG        = DXREG*SCRATCH
+X_CXREG        = CXREG*SCRATCH
+X_SIREG        = SIREG*SCRATCH
+X_DIREG        = DIREG*SCRATCH
+X_ADDREG       = ADDREG*SCRATCH
+
+/* Mode refering to a word in memory */
+memory2        = EXTERN2 + ind_reg2 + ind_regoff2 + ind_bpregoff2 + LOCAL2
+
+/* Mode refering to a byte in memory */
+memory1        = EXTERN1 + ind_reg1 + ind_regoff1 + ind_bpregoff1 + LOCAL1
+
+/* Modes allowed in instructions */
+const          = ANYCON + ADDR_EXTERN
+anyreg         = REG + BREG
+rm             = anyreg + memory2
+rmorconst      = const + rm
+regorconst     = const + anyreg
+dest           = REG + memory2
+
+rm1            = REG1 + memory1
+rmorconst1     = const + rm1
+regorconst12   = REG1 + GENREG + const
+dest1          = REG1 + memory1
+
+/* Modes used to indicate tokens to be removed from the fakestack */
+reg_indexed    = ind_reg2 + ind_regoff2 + ind_reg1 + ind_regoff1
+lb_indexed     = ind_bpregoff2 + ind_bpregoff1
+indexed        = reg_indexed + lb_indexed
+externals      = EXTERN2 + EXTERN1
+locals         = LOCAL2 + LOCAL1
+all_locals     = locals + lb_indexed
+indirects      = externals + reg_indexed
+referals       = indirects + locals
+
+/* Miscellaneous */
+halfindir      = reg_off + bpreg_off + ADDR_LOCAL
+some_off       = halfindir + ADDR_EXTERN + ADDREG
+a_word         = rmorconst + rm1 + halfindir
+no_reg_off     = rmorconst + rm1 + ADDR_LOCAL
+
+CODE:
+
+/********************************************************
+ * Group 1 : load instructions.                        *
+ *                                                     *
+ * For most load instructions no code is generated.    *
+ * Action : put something on the fake-stack.           *
+ ********************************************************/
+
+loc            | |             | {ANYCON, $1}                          | |
+ldc            | |             | {ANYCON, highw(1)} {ANYCON, loww(1)}  | |
+lol            | |             | {LOCAL2, $1, 2}                       | |
+loe            | |             | {EXTERN2, $1}                         | |
+lil            | |     allocate(ADDREG={ind_regoff2, bp, tostring($1)})
+                               | {ind_reg2, %[a]}                      | |
+lof            | nocoercions : reg_off |
+                               | {ind_regoff2, %[1.reg],
+                                       %[1.off]+"+"+tostring($1)}      | |
+...            | ADDREG |      | {ind_regoff2,%[1],tostring($1)} | |
+...            | nocoercions : bpreg_off  |
+                         | {ind_bpregoff2,%[1.reg], %[1.ind]+$1} | |
+...            | nocoercions : ADDR_EXTERN|
+                           | {EXTERN2,%[1.off]+"+"+tostring($1)} | |
+...            | nocoercions : ADDR_LOCAL |
+                                     | {LOCAL2, %[1.ind] + $1,2} | |
+lal            | |             | {ADDR_LOCAL, $1}                      | |
+lae            | |             | {ADDR_EXTERN, $1}                     | |
+lpb            | |             |                       | adp SL  |
+lxl $1==0      | |             | {ADDR_LOCAL, 0}                       | |
+lxl $1==1      | |             | {LOCAL2 ,SL, 2}                       | |
+lxl $1==2      | |     allocate(ADDREG={ind_regoff2, bp, SSL})
+                               | {ind_regoff2,%[a], SSL}               | |
+lxl $1>2       | |     allocate(ADDREG={ind_regoff2, bp, SSL},
+                                CXREG={ANYCON,$1-1})
+                       "1:\tmov %[a],4(%[a])"
+                       "loop 1b"
+                       samecc erase(%[a]) erase(%[b])
+                               | %[a]                                  | |
+lxa $1==0      | |             | {ADDR_LOCAL, SL}                      | |
+lxa $1==1      | |     allocate(ADDREG={ind_regoff2, bp, SSL })
+                               | {reg_off, %[a], SSL }                 | |
+lxa $1==2      | |     allocate(ADDREG={ind_regoff2, bp, SSL })
+                       move({ind_regoff2, %[a], SSL }, %[a])
+                               | {reg_off, %[a], SSL }                 | |
+lxa $1 > 2     | |     allocate(ADDREG={ind_regoff2,bp,SSL},
+                                CXREG={ANYCON,$1-1})
+                       "1:\tmov %[a],4(%[a])"
+                       "loop 1b"
+                       samecc erase(%[a]) erase(%[b])
+                               | {reg_off, %[a], SSL }                 | |
+dch            | |             |                              | loi 2    |
+loi $1==2      | ADDREG     |  | {ind_reg2, %[1]}                      | |
+...            | nocoercions : reg_off    |
+                           | {ind_regoff2, %[1.reg], %[1.off]} | |
+...            | nocoercions : bpreg_off  |
+                       | {ind_bpregoff2, %[1.reg], %[1.ind]}   | |
+...            | nocoercions : ADDR_EXTERN|
+                       | {EXTERN2, %[1.off]}                   | |
+...            | nocoercions : ADDR_LOCAL |
+                       | {LOCAL2, %[1.ind],2}                  | |
+loi $1==1      | ADDREG     |  | {ind_reg1, %[1]}                      | |
+...            | nocoercions : reg_off    |
+                               | {ind_regoff1, %[1.reg], %[1.off]}     | |
+...            | nocoercions : bpreg_off  |
+                       | {ind_bpregoff1, %[1.reg], %[1.ind]}   | |
+...            | nocoercions : ADDR_EXTERN |
+                       | {EXTERN1, %[1.off]}                   | |
+...            | nocoercions : ADDR_LOCAL |
+                       | {LOCAL1, %[1.ind],1}                  | |
+loi $1==4      | ADDREG     |  | {ind_regoff2,%[1],"2"} {ind_reg2,%[1]}| |
+...            | nocoercions : reg_off    |
+                               | {ind_regoff2,%[1.reg], %[1.off]+"+2"}
+                                 {ind_regoff2,%[1.reg], %[1.off]}      | |
+...            | nocoercions : bpreg_off  |
+                       | {ind_bpregoff2, %[1.reg], %[1.ind]+2}
+                                 {ind_bpregoff2, %[1.reg], %[1.ind]}   | |
+...            | nocoercions : ADDR_LOCAL |    |
+                             {LOCAL2,%[1.ind]+2,2} {LOCAL2,%[1.ind],2} | |
+...            | nocoercions : ADDR_EXTERN|    | {EXTERN2, %[1.off]+"+2"}
+                                 {EXTERN2, %[1.off]}                   | |
+loi $1>4       | X_SIREG |
+                       remove(ALL)
+                       allocate(CXREG={ANYCON,$1})
+                       "sub sp,cx"
+                       "sar cx,1"
+                       "mov di,sp"
+                       "rep movs"
+                       erase(%[a]) erase(%[1]) | | | (8,8+$1*9)
+...            | X_SIREG |
+                       remove(ALL)
+                       allocate(CXREG={ANYCON,$1})
+                       "call .loi"
+                       erase(%[a]) erase(%[1]) | | | (3,32+$1*9)
+los $1==2      | X_CXREG X_SIREG |
+                       remove(ALL)
+                       "call .loi"
+                       erase(%[1]) erase(%[2])                 |       | |
+los !defined($1)| rm X_CXREG X_SIREG |
+                       remove(ALL)
+                       "cmp %[1],2"
+                       "jne .unknown"
+                       "call .loi"
+                       erase(%[2]) erase(%[3])                 |       | |
+ldl            | |             | {LOCAL2, $1+2,2} {LOCAL2, $1,2}       | |
+lde            | |             | {EXTERN2, $1+"+2"} {EXTERN2, $1}      | |
+ldf            | nocoercions : reg_off |
+                               | {ind_regoff2, %[1.reg],
+                                       %[1.off]+"+2+"+tostring($1)}
+                                 {ind_regoff2, %[1.reg],
+                                       %[1.off]+"+"+tostring($1)}      | |
+...            | ADDREG |
+                               | {ind_regoff2, %[1], tostring($1+2)}
+                                 {ind_regoff2, %[1], tostring($1)}     | |
+...            | nocoercions : bpreg_off |
+                               | {ind_bpregoff2,%[1.reg], %[1.ind]+2+$1}
+                                 {ind_bpregoff2,%[1.reg], %[1.ind]+$1} | |
+...            | nocoercions : ADDR_EXTERN |
+                               | {EXTERN2,%[1.off]+"+2+"+tostring($1)}
+                                 {EXTERN2,%[1.off]+"+"+tostring($1)}   | |
+...            | nocoercions : ADDR_LOCAL |
+                               | {LOCAL2, %[1.ind] + $1 + 2, 2}
+                                 {LOCAL2, %[1.ind] + $1, 2}            | |
+lpi            | |             | {ADDR_EXTERN, $1}                     | |
+/* This code sequence is generated by the C-compiler to tackle
+   char parameters, on the 8086 it reduces to nil */
+lol lal sti $1==$2 && $3<=2 | | |                                      | |
+
+/****************************************************************
+ * Group 2 : Store instructions.                               *
+ *                                                             *
+ * These instructions are likely to ruin the fake-stack.       *
+ * We don't expect many items on the fake-stack anyway         *
+ * because we seem to have evaluated an expression just now.   *
+ ****************************************************************/
+
+stl            | regorconst |
+                       remove(indexed)
+                       remove(locals, %[ind]>=$1 && %[ind]<$1+2 )
+                       move(%[1],{ind_regoff2,bp,tostring($1)})|       | |
+...            | nocoercions : STACK |
+                       "pop $1(bp)" samecc                     |  | |(2,26)
+ste            | regorconst |
+                       remove(indirects)
+                       move(%[1], {EXTERN2, $1 })              |       | |
+...            | nocoercions : STACK | "pop ($1)" samecc       | | |
+sil            | regorconst |
+                       allocate(ADDREG={ind_regoff2, bp, tostring($1)})
+                       remove(referals)
+                       move(%[1], {ind_reg2, %[a]})            |       | |
+stf            | ADDREG regorconst |
+                       remove(referals)
+                       move(%[2],{ind_regoff2,%[1],tostring($1)})|     | |
+...            | nocoercions : ADDREG STACK |
+                       remove(referals)
+                       "pop $1(%[1])" samecc                         | | |
+...            | reg_off regorconst |
+                       remove(referals)
+                       move(%[2],{ind_regoff2,%[1.reg],
+                               %[1.off]+"+"+tostring($1)})     |       | |
+...            | nocoercions : halfindir STACK |
+                       remove(referals)
+                       "pop $1+%[1]" samecc                          | | |
+...            | ADDR_LOCAL | |                        | stl %[1.ind]+$1 |
+...            | bpreg_off regorconst |
+                       remove(all_locals)
+                       remove(indexed)
+                       move(%[2],{ind_bpregoff2,%[1.reg],
+                                       %[1.ind]+$1})           |       | |
+/*
+...            | ADDR_EXTERN regorconst |
+                       remove(indirects)
+                       move(%[2],{EXTERN2,%[1.off]+"+"+tostring($1)})| | |
+*/
+sti $1==2      | ADDREG regorconst |
+                       remove(referals)
+                       move(%[2],{ind_reg2,%[1]})              |       | |
+...            | nocoercions : ADDREG STACK |
+                       remove(referals)
+                       "pop (%[1])" samecc                           | | |
+...            | reg_off regorconst |
+                       remove(referals)
+                       move(%[2],{ind_regoff2,%[1.reg],%[1.off]})  |   | |
+...            | nocoercions : reg_off STACK |
+                       remove(referals)
+                       "pop %[1]" samecc                             | | |
+...            | ADDR_LOCAL |                          | | stl %[1.ind] |
+...            | bpreg_off regorconst |
+                       remove(all_locals)
+                       remove(indexed)
+                       move(%[2],{ind_bpregoff2,%[1.reg], %[1.ind]}) | | |
+...            | nocoercions : bpreg_off STACK |
+                       remove(all_locals)
+                       remove(indexed)
+                       "pop %[1]" samecc                             | | |
+...            | ADDR_EXTERN regorconst |
+                       remove(indirects)
+                       move(%[2],{EXTERN2,%[1.off]})           |       | |
+...            | nocoercions : ADDR_EXTERN STACK |
+                       remove(indirects)
+                       "pop (%[1])" samecc                           | | |
+sti $1==1      | ADDREG regorconst12 |
+                       remove(referals)
+                       move(%[2],{ind_reg1,%[1]})              |       | |
+...            | reg_off regorconst12 |
+                       remove(referals)
+                       move(%[2],{ind_regoff1,%[1.reg],%[1.off]})  |   | |
+...            | bpreg_off regorconst12 |
+                       remove(all_locals)
+                       remove(indexed)
+                       move(%[2],{ind_bpregoff1,%[1.reg], %[1.ind]}) | | |
+...            | ADDR_EXTERN regorconst12 |
+                       remove(indirects)
+                       move(%[2],{EXTERN1,%[1.off]})           |       | |
+...            | ADDR_LOCAL regorconst12 |
+                       remove(indexed)
+                       remove(locals,
+                               %[ind]<=%[1.ind] && %[ind]+%[size]>%[1.ind] )
+                       move(%[2],{ind_regoff1, bp, tostring(%[1.ind])})
+                                                               |       | |
+sti $1==4      | ADDREG regorconst regorconst |
+                       remove(referals)
+                       move(%[2],{ind_reg2,%[1]})
+                       move(%[3],{ind_regoff2,%[1],"2"})       |       | |
+...            | reg_off regorconst regorconst |
+                       remove(referals)
+                       move(%[2],{ind_regoff2,%[1.reg],%[1.off]})
+                       move(%[3],{ind_regoff2,%[1.reg],%[1.off]+"+2"})| | |
+...            | bpreg_off regorconst regorconst |
+                       remove(all_locals)
+                       remove(indexed)
+                       move(%[2],{ind_bpregoff2,%[1.reg], %[1.ind]})
+                       move(%[3],{ind_bpregoff2,%[1.reg], %[1.ind]+2})| | |
+...            | ADDR_EXTERN regorconst regorconst |
+                       remove(indirects)
+                       move(%[2],{EXTERN2,%[1.off]})
+                       move(%[3],{EXTERN2,%[1.off]+"+2"})      |       | |
+...            | ADDR_LOCAL regorconst regorconst |
+                       remove(indexed)
+                       remove(locals, %[ind]>=%[1.ind] && %[ind]<%[1.ind]+4 )
+                       move(%[2],{ind_regoff2, bp, tostring(%[1.ind])})
+                       move(%[3],{ind_regoff2, bp,
+                                               tostring(%[1.ind]+2)})| | |
+sti $1>4       | X_DIREG |
+                       remove(ALL)
+                       allocate(CXREG={ANYCON,$1/2})
+                       "mov si,sp"
+                       "rep movs"
+                       "mov sp,si"
+                       erase(%[1]) erase(%[a]) |       | | (5,4+$1*8)
+/* This sort of construction gives problems in the codegenerator
+   because of the potential verly large lookahead
+...            | X_ADDREG |
+                       remove(ALL)
+                       "pop (%[1])"
+                       "add %[1],2"
+                       erase(%[1])             | %[1]  | sti $1-2 | (5,30)
+*/
+sts $1==2      | X_CXREG X_DIREG |
+                       remove(ALL)
+                       "call .sti"
+                       erase(%[1]) erase(%[2])                 |       | |
+sdl            |         |                       |     | stl $1 stl $1+2 |
+sde            |         |                       |  | ste $1 ste $1+"+2" |
+sdf            | ADDREG regorconst regorconst |
+                       remove(referals)
+                       move(%[2],{ind_regoff2,%[1],tostring($1)})
+                       move(%[3],{ind_regoff2,%[1],tostring($1+2)})|   | |
+...            | nocoercions : ADDREG STACK |
+                       remove(referals)
+                       "pop $1(%[1])"
+                       "pop %($1+2%)(%[1])" samecc                   | | |
+...            | reg_off regorconst regorconst |
+                       remove(referals)
+                       move(%[2],{ind_regoff2,%[1.reg],
+                               %[1.off]+"+"+tostring($1)})
+                       move(%[3],{ind_regoff2,%[1.reg],
+                               %[1.off]+"+"+tostring($1+2)})   |       | |
+...            | nocoercions : halfindir STACK |
+                       remove(referals)
+                       "pop $1+%[1]"
+                       "pop %($1+2%)+%[1]" samecc                    | | |
+       /* Funny things happen when the sign changes in the stl parameters */
+...            | ADDR_LOCAL | |      | stl %[1.ind]+$1 stl %[1.ind]+$1+2 |
+...            | bpreg_off regorconst regorconst |
+                       remove(all_locals)
+                       remove(indexed)
+                       move(%[2],{ind_bpregoff2,%[1.reg],
+                                       %[1.ind]+$1})
+                       move(%[3],{ind_bpregoff2,%[1.reg],
+                                       %[1.ind]+$1+2})         |       | |
+...            | halfindir regorconst |
+                       remove(referals)
+                       "mov %[1],%[2]"
+                       samecc | %[1] | stf $1+2 | (0,12)+%[1]+%[2]+%[1]
+
+/****************************************************************
+ * Group 3 : Integer arithmetic.                               *
+ *                                                             *
+ * Implemented (sometimes with the use of subroutines) :       *
+ * all 2 and 4 byte arithmetic.                                *
+ ****************************************************************/
+
+adi $1==2      | NO X_REG rmorconst |
+                       "add %[1],%[2]"
+                       erase(%[1]) setcc(%[1]) | %[1]  | | (2,3) + %[2]
+...            | rmorconst X_REG |
+                       "add %[2],%[1]"
+                       erase(%[2]) setcc(%[2]) | %[2]  | | (2,3) + %[1]
+...            | X_ACC const |
+                       "add %[1],%[2]"
+                       erase(%[1]) setcc(%[1]) | %[1]  | | (3,4)
+...            | const X_ACC |
+                       "add %[2],%[1]"
+                       erase(%[2]) setcc(%[2]) | %[2]  | | (3,4)
+adi $1==4      | NO X_REG X_REG rmorconst rmorconst |
+                       "add %[1],%[3]"
+                       "adc %[2],%[4]"
+                       setcc(%[2]) erase(%[1]) erase(%[2])
+                                               | %[2] %[1] | |(4,6)+%[4]+%[3]
+...            | X_ACC X_REG const rmorconst |
+                       "add %[1],%[3]"
+                       "adc %[2],%[4]"
+                       setcc(%[2]) erase(%[1]) erase(%[2])
+                                               | %[2] %[1] | |(5,7)+%[4]
+...            | rmorconst rmorconst X_REG X_REG |
+                       "add %[3],%[1]"
+                       "adc %[4],%[2]"
+                       setcc(%[4]) erase(%[3]) erase(%[4])
+                                               | %[4] %[3] | |(4,6)+%[1]+%[2]
+...            | const rmorconst X_ACC X_REG |
+                       "add %[3],%[1]"
+                       "adc %[4],%[2]"
+                       setcc(%[4]) erase(%[3]) erase(%[4])
+                                               | %[4] %[3] | |(5,7)+%[2]
+adi !defined($1)| X_CXREG X_ACC |
+                       remove(ALL)
+                       "call .adi"
+                       erase(%[1]) erase(%[2])        | ax | |
+sbi $1==2      | rmorconst X_REG |
+                       "sub %[2],%[1]"
+                       erase(%[2]) setcc(%[2])      | %[2] | | (2,3) + %[1]
+...            | const X_ACC |
+                       "sub %[2],%[1]"
+                       erase(%[2]) setcc(%[2])      | %[2] | | (3,4)
+...            | NO X_REG rmorconst |
+                       "sub %[1],%[2]"
+                       "neg %[1]"
+                       erase(%[1]) setcc(%[1])      | %[1] | | (4,6) + %[2]
+...            | NO X_ACC const |
+                       "sub %[1],%[2]"
+                       "neg %[1]"
+                       erase(%[1]) setcc(%[1])      | %[1] | | (5,7)
+sbi $1==4      | rmorconst rmorconst X_REG X_REG |
+                       "sub %[3],%[1]"
+                       "sbb %[4],%[2]"
+                       setcc(%[4]) erase(%[3]) erase(%[4])
+                                               | %[4] %[3] | |(4,6)+%[1]+%[2]
+...            | const rmorconst-ACC X_ACC X_REG |
+                       "sub %[3],%[1]"
+                       "sbb %[4],%[2]"
+                       setcc(%[4]) erase(%[3]) erase(%[4])
+                                               | %[4] %[3] | |(5,7)+%[2]
+sbi !defined($1)| X_CXREG X_ACC |
+                       remove(ALL)
+                       "call .sbi"
+                       erase(%[1]) erase(%[2])        | ax | |
+mli $1==2      | X_ACC rm |
+                       allocate(%[2],DXREG)
+                       "mul %[2]"
+                       /* mul and imul have same low order result
+                          but mul is faster
+                       */
+                       nocc erase(%[1])            | %[1]  | |(2,118)+%[2]
+...            | rm-ACC X_ACC |
+                       allocate(%[1],DXREG)
+                       "mul %[1]"
+                       nocc erase(%[2])            | %[2]  | |(2,118)+%[1]
+mli $1==4      | SIREG DIREG BXREG X_ACC |
+                       remove(ALL)
+                       "call .mli4"
+                       erase(ax) setcc(dx)         | dx ax | |
+/* Not now,
+mli !defined($1)| X_ACC |
+                       remove(ALL)
+                       "call .mli"                 |       | |
+*/
+dvi $1==2      | rm-ACC X_ACC |
+                       allocate(DXREG)
+                       "cwd"
+                       "idiv %[1]"
+                       erase(%[2])                    | ax | |(3,176)+%[1]
+dvi $1==4      | |     remove(ALL)
+                       "call .dvi4"                | cx ax | |
+/*
+dvi !defined($1)| X_ACC |
+                       remove(ALL)
+                       "call .dvi" erase(%[1])     |       | |
+*/
+#ifdef LONGEMPAT
+loc loc cii dvi loc loc cii $1==2 && $2==4 && $4==4 && $5==4 && $6==2
+               | rm-ACC-DXREG X_ACC X_DXREG |
+                       "idiv %[1]"
+                       erase(%[2]) erase(%[3])        | ax | |(2,171)+%[1]
+#endif
+rmi $1==2      | rm-ACC X_ACC |
+                       allocate(DXREG)
+                       "cwd"
+                       "idiv %[1]"
+                       erase(%[2])                    | dx | |(3,176)+%[1]
+rmi $1==4      | |     remove(ALL)
+                       "call .rmi4"                | bx dx | |
+/*
+rmi !defined($1)| X_ACC |
+                       remove(ALL)
+                       "call .rmi" erase(%[1])     |       | |
+*/
+#ifdef LONGEMPAT
+loc loc cii rmi loc loc cii $1==2 && $2==4 && $4==4 && $5==4 && $6==2
+               | rm-ACC-DXREG X_ACC X_DXREG |
+                       "idiv %[1]"
+                       erase(%[2]) erase(%[3])        | dx | |(2,171)+%[1]
+#endif
+ngi $1==2      | X_REG |
+                       "neg %[1]"
+                       setcc(%[1]) erase(%[1])     | %[1]  | |(2,3)
+ngi $1==4      | X_REG X_REG |
+                       "neg %[2]"
+                       "neg %[1]"
+                       "sbb %[2],0"
+                       setcc(%[2]) erase(%[1]) erase(%[2])
+                                               | %[2] %[1] | | (8,10)
+...            | X_REG-ACC X_ACC |
+                       "neg %[2]"
+                       "neg %[1]"
+                       "sbb %[2],0"
+                       setcc(%[2]) erase(%[1]) erase(%[2])
+                                               | %[2] %[1] | | (7,10)
+/*
+ngi !defined($1)| X_ACC |
+                       remove(ALL)
+                       "call .ngi"                 |       | |
+*/
+loc sli $1==1 && $2==2 | X_REG |
+                       "sal %[1],1"
+                       setcc(%[1]) erase(%[1])      | %[1] | | (2,2)
+sli $1==2      | SHIFT_CREG X_REG |
+                       "sal %[2],cl"
+                       setcc(%[2]) erase(%[2])     | %[2]  | | (2,8)
+sli $1==4      | X_CXREG X_REG X_REG |
+                       "jcxz 1f"
+                       "2: sal %[2],1"
+                       "rcl %[3],1"
+                       "loop 2b\n1:"
+                       erase(%[1]) erase(%[2]) erase(%[3])
+                                               | %[3] %[2] | |
+/*
+sli !defined($1)| X_ACC |
+                       remove(ALL)
+                       "call .sli"                 |       | |
+*/
+loc sri $1==1 && $2==2 | X_REG |
+                       "sar %[1],1"
+                       setcc(%[1]) erase(%[1])      | %[1] | | (2,2)
+sri $1==2      | SHIFT_CREG X_REG |
+                       "sar %[2],cl"
+                       setcc(%[2]) erase(%[2])     | %[2]  | | (2,8)
+sri $1==4      | X_CXREG X_REG X_REG |
+                       "jcxz 1f"
+                       "2: sar %[3],1"
+                       "rcr %[2],1"
+                       "loop 2b\n1:"
+                       erase(%[1]) erase(%[2]) erase(%[3])
+                                               | %[3] %[2] | |
+/*
+sri !defined($1)| X_ACC |
+                       remove(ALL)
+                       "call .sri"                 |       | |
+*/
+
+
+/************************************************
+ * Group 4 : unsigned arithmetic               *
+ *                                             *
+ * adu = adi                                   *
+ * sbu = sbi                                   *
+ * slu = sli                                   *
+ * mlu = mli                                   *
+ *                                             *
+ * Supported : 2- and 4 byte arithmetic.       *
+ ************************************************/
+
+adu            | |     |                                   | adi $1 |
+sbu            | |     |                                   | sbi $1 |
+mlu            | |     |                                   | mli $1 |
+dvu $1==2      | rm-ACC X_ACC |
+                       allocate(%[1],DXREG={ANYCON,0})
+                       "div %[1]"
+                       erase(%[2]) erase(%[a])      | %[2] | |(2,149)+%[1]
+dvu $1==4      | |     remove(ALL)
+                       "call .dvu4"                | cx ax | |
+/*
+dvu !defined($1)| X_ACC |
+                       remove(ALL)
+                       "call .dvu" erase(%[1])     |       | |
+*/
+rmu $1==2      | rm-ACC X_ACC |
+                       allocate(%[1],DXREG={ANYCON,0})
+                       "div %[1]"
+                       erase(%[2]) erase(%[a])        | dx | |(3,149)+%[1]
+rmu $1==4      | |     remove(ALL)
+                       "call .rmu4"                | bx dx | |
+/*
+rmu !defined($1)| X_ACC |
+                       remove(ALL)
+                       "call .rmu" erase(%[1])     |       | |
+*/
+slu            | |     |                                   | sli $1 |
+loc sru $1==1 && $2==2 | X_REG |
+                       "shr %[1],1"
+                       setcc(%[1]) erase(%[1])      | %[1] | | (2,2)
+sru $1==2      | SHIFT_CREG X_REG |
+                       "shr %[2],cl"
+                       setcc(%[2]) erase(%[2])      | %[2] | | (2,8)
+sru $1==4      | X_CXREG X_REG X_REG |
+                       "jcxz 1f" /* result => samecc */
+                       "2: shr %[3],1"
+                       "rcr %[2],1"
+                       "loop 2b\n1:"
+                       erase(%[1]) erase(%[2]) erase(%[3])
+                                               | %[3] %[2] | |
+/*
+sru !defined($1)| X_ACC |
+                       remove(ALL)
+                       "call .sru"                 |       | |
+*/
+
+/************************************************
+ * Group 5 : Floating point arithmetic         *
+ *                                             *
+ ************************************************/
+
+adf $1==4      | |
+                       remove(ALL)
+                       "call .adf4"                |       | |
+adf $1==8      | |
+                       remove(ALL)
+                       "call .adf8"                |       | |
+adf !defined($1)       | X_CXREG |
+                       remove(ALL)
+                       "call .adf" erase(%[1])     |       | |
+sbf $1==4      | |
+                       remove(ALL)
+                       "call .sbf4"                |       | |
+sbf $1==8      | |
+                       remove(ALL)
+                       "call .sbf8"                |       | |
+sbf !defined($1)       | X_CXREG |
+                       remove(ALL)
+                       "call .sbf" erase(%[1])     |       | |
+mlf $1==4      | |
+                       remove(ALL)
+                       "call .mlf4"                |       | |
+mlf $1==8      | |
+                       remove(ALL)
+                       "call .mlf8"                |       | |
+mlf !defined($1)       | X_CXREG |
+                       remove(ALL)
+                       "call .mlf" erase(%[1])     |       | |
+dvf $1==4      | |
+                       remove(ALL)
+                       "call .dvf4"                |       | |
+dvf $1==8      | |
+                       remove(ALL)
+                       "call .dvf8"                |       | |
+dvf !defined($1)       | X_CXREG |
+                       remove(ALL)
+                       "call .dvf" erase(%[1])     |       | |
+ngf $1==4      | |
+                       remove(ALL)
+                       "call .ngf4"                |       | |
+ngf $1==8      | |
+                       remove(ALL)
+                       "call .ngf8"                |       | |
+ngf !defined($1)       | X_CXREG |
+                       remove(ALL)
+                       "call .ngf" erase(%[1])     |       | |
+fif $1==4      | |
+                       remove(ALL)
+                       "call .fif4"                |       | |
+fif $1==8      | |
+                       remove(ALL)
+                       "call .fif8"                |       | |
+fif !defined($1)       | X_CXREG |
+                       remove(ALL)
+                       "call .fif" erase(%[1])     |       | |
+fef $1==4      | |
+                       remove(ALL)
+                       "call .fef4"                |       | |
+fef $1==8      | |
+                       remove(ALL)
+                       "call .fef8"                |       | |
+fef !defined($1)       | X_CXREG |
+                       remove(ALL)
+                       "call .fef" erase(%[1])     |       | |
+
+
+
+/****************************************
+ * Group 6 : pointer arithmetic.       *
+ *                                     *
+ * Pointers have size 2 bytes.         *
+ ****************************************/
+
+adp $1==1      | nocoercions : reg_off | |
+                         {reg_off, %[1.reg],%[1.off]+"+"+tostring($1)} | |
+...            | nocoercions : ADDR_EXTERN | |
+                              {ADDR_EXTERN, %[1.off]+"+"+tostring($1)} | |
+...            | nocoercions : ADDR_LOCAL | |
+                                            {ADDR_LOCAL, %[1.ind]+$1 } | |
+...            | nocoercions : bpreg_off | |
+                                    {bpreg_off, %[1.reg], %[1.ind]+$1} | |
+...            | X_REG |
+                       "inc %[1]"
+                       erase(%[1]) setcc(%[1])   | %[1]        | | (1,2)
+adp $1 == 0-1  | nocoercions : reg_off | |
+                             {reg_off, %[1.reg],%[1.off]+tostring($1)} | |
+...            | nocoercions : ADDR_EXTERN | |
+                                  {ADDR_EXTERN, %[1.off]+tostring($1)} | |
+...            | nocoercions : ADDR_LOCAL| |{ADDR_LOCAL, %[1.ind]+$1 } | |
+...            | nocoercions : bpreg_off | |
+                                    {bpreg_off, %[1.reg], %[1.ind]+$1} | |
+...            | X_REG |
+                       "dec %[1]"
+                       erase(%[1]) setcc(%[1])   | %[1]        | | (1,2)
+adp            | nocoercions : reg_off | |
+                         {reg_off, %[1.reg],%[1.off]+"+"+tostring($1)} | |
+...            | nocoercions : ADDR_EXTERN | |
+                              {ADDR_EXTERN, %[1.off]+"+"+tostring($1)} | |
+...            | nocoercions : ADDR_LOCAL | |
+                                            {ADDR_LOCAL, %[1.ind]+$1 } | |
+...            | nocoercions : bpreg_off | |
+                                    {bpreg_off, %[1.reg], %[1.ind]+$1} | |
+...            | X_ADDREG | |            {reg_off, %[1], tostring($1)} | |
+...            | nocoercions : X_ACC + X_CXREG + X_DXREG |
+                       "add %[1],$1"
+                       erase(%[1]) setcc(%[1]) | %[1]  | | (4,4)
+ads $1==2      | nocoercions : ANYCON reg_off |  |
+                       {reg_off, %[2.reg],
+                               %[2.off]+"+"+tostring(%[1.val])}        | |
+...            | nocoercions : ADDR_EXTERN reg_off | |
+                       {reg_off, %[2.reg], %[2.off]+"+"+%[1.off]}      | |
+...            | rm reg_off |
+                       "add %[2.reg],%[1]"
+                       erase(%[2.reg]) setcc(%[2.reg]) |
+                         {reg_off, %[2.reg], %[2.off]} | | (2,3) + %[1]
+...            | nocoercions : ANYCON bpreg_off | |
+                             {bpreg_off, %[2.reg], %[2.ind]+%[1.val]} | |
+...            | rm bpreg_off |
+                       "add %[2.reg],%[1]"
+                       erase(%[2.reg]) setcc(%[2.reg]) |
+                       {bpreg_off, %[2.reg], %[2.ind]} | | (2,3) + %[1]
+...            | reg_off rmorconst |
+                       "add %[1.reg],%[2]"
+                       erase(%[1.reg]) setcc(%[1.reg]) |
+                         {reg_off, %[1.reg], %[1.off]} | | (2,3) + %[2]
+...            | bpreg_off rmorconst |
+                       "add %[1.reg],%[2]"
+                       erase(%[1.reg]) setcc(%[1.reg]) |
+                       {bpreg_off, %[1.reg], %[1.ind]} | | (2,3) + %[2]
+...            | nocoercions : reg_off ANYCON |  |
+                       {reg_off, %[1.reg],
+                                 %[1.off]+"+"+tostring(%[2.val])}     | |
+...            | nocoercions : reg_off ADDR_EXTERN | |
+                           {reg_off, %[1.reg], %[1.off]+"+"+%[2.off]} | |
+...            | nocoercions : reg_off reg_off |
+                       "add %[1.reg],%[2.reg]"
+                       erase(%[1.reg]) setcc(%[1.reg]) |
+              {reg_off,%[1.reg],%[1.off]+"+"+%[2.off]} | | (2,3)
+...            | IREG ADDR_LOCAL |       | {bpreg_off,%[1],%[2.ind]} | |
+/*
+...            | (REG-IREG) ADDR_LOCAL |
+                       allocate(%[1],ADDREG=%[1])
+                       "add %[a],bp"
+                 | {reg_off, %[a], tostring(%[2.ind])} | | (2,3)
+*/
+#ifdef DEEPER
+...            | X_REG rmorconst |
+                       "add %[1],%[2]"
+                       erase(%[1]) setcc(%[1]) | %[1]  | | (2,3) + %[2]
+...            | rmorconst X_REG |
+                       "add %[2],%[1]"
+                       erase(%[2]) setcc(%[2]) | %[2]  | | (2,3) + %[1]
+...            | X_ACC const |
+                       "add %[1],%[2]"
+                       erase(%[1]) setcc(%[1]) | %[1]  | | (3,4)
+...            | const X_ACC |
+                       "add %[2],%[1]"
+                       erase(%[2]) setcc(%[2]) | %[2]  | | (3,4)
+#else
+...            | X_ADDREG ADDR_EXTERN | |      {reg_off, %[1], %[2.off]} | |
+...            | X_ADDREG rm |
+                       "add %[1],%[2]"
+                       erase(%[1]) setcc(%[1]) | %[1]  | | (2,3) + %[2]
+...            | ADDR_EXTERN X_ADDREG | |      {reg_off, %[2], %[1.off]} | |
+...            | rm X_ADDREG |
+                       "add %[2],%[1]"
+                       erase(%[2]) setcc(%[2]) | %[2]  | | (2,3) + %[1]
+#endif
+sbs $1==2      | nocoercions : ANYCON reg_off |   |
+                  {reg_off, %[2.reg], %[2.off]+"-"+tostring(%[1.val])} | |
+...            | nocoercions : ANYCON ADDR_LOCAL | |
+                                       {ADDR_LOCAL, %[2.ind]-%[1.val]} | |
+...            | rm reg_off |
+                       "sub %[2.reg],%[1]"
+                       erase(%[2.reg]) setcc(%[2.reg]) |
+                                         {reg_off, %[2.reg], %[2.off]} | |
+/*     Should not occur
+...            | nocoercions : reg_off ANYCON |   |
+                  {reg_off, %[1.reg], %[1.off]+"-"+tostring(%[2.val])} | |
+...            | ANYCON ADDR_EXTERN | |
+                        {ADDR_EXTERN, %[2.off]+"+"+tostring(%[1.val])} | |
+...            | nocoercions : ANYCON ADDR_LOCAL | |
+                                       {ADDR_LOCAL, %[1.val]+%[2.ind]} | |
+*/
+...            | rm X_REG |
+                       "sub %[2],%[1]"
+                       erase(%[2]) setcc(%[2]) | %[2]  | | (2,3) + %[1]
+...            | const X_ACC |
+                       "sub %[2],%[1]"
+                       erase(%[2]) setcc(%[2]) | %[2]  | | (3,4)
+
+/****************************************
+ * Group 7 : increment/decrement/zero  *
+ ****************************************/
+
+inc            | X_REG |
+                       "inc %[1]"
+                       setcc(%[1]) erase(%[1])      | %[1] | |(1,2)
+inl            | |     remove(indexed)
+                       remove(locals, %[ind]>=$1 && %[ind]<$1+2 )
+                       "inc $1(bp)"
+                       setcc({LOCAL2,$1,2})         |      | |(3,24)
+ine            | |     remove(indirects)
+                       "inc ($1)"
+                       setcc({EXTERN2,$1})          |      | |(4,21)
+dec            | X_REG |
+                       "dec %[1]"
+                       setcc(%[1]) erase(%[1])      | %[1] | |(1,2)
+del            | |     remove(indexed)
+                       remove(locals, %[ind]>=$1 && %[ind]<$1+2 )
+                       "dec $1(bp)"
+                       setcc({LOCAL2,$1,2})         |      | |(3,24)
+dee            | |     remove(indirects)
+                       "dec ($1)"
+                       setcc({EXTERN2,$1})          |      | |(4,21)
+zrl            | |     remove(indexed)
+                       remove(locals, %[ind]>=$1 && %[ind]<$1+2 )
+                       move({ANYCON,0},{LOCAL2,$1,2})
+                                                    |      | |
+zre            | |     remove(indirects)
+                       move({ANYCON,0},{EXTERN2,$1})|      | |
+zrf $1==4      | |
+                       remove(ALL)
+                       "call .zrf4"                |       | |
+zrf $1==8      | |
+                       remove(ALL)
+                       "call .zrf8"                |       | |
+zrf !defined($1)       | X_CXREG |
+                       remove(ALL)
+                       "call .zrf" erase(%[1])     |       | |
+zer $1==2      | |                            | {ANYCON,0} | |
+zer $1==4      | |                 | {ANYCON,0} {ANYCON,0} | |
+zer $1==6      | |                 | {ANYCON,0} {ANYCON,0}
+                                                {ANYCON,0} | |
+zer $1==8      | |                 | {ANYCON,0} {ANYCON,0}
+                                     {ANYCON,0} {ANYCON,0} | |
+zer defined($1) | |    remove(ALL)
+                       move({ANYCON,$1/2},cx)
+                       move({ANYCON,0},bx)
+                       "1: push bx"
+                       "loop 1b"
+                       samecc erase(cx)                  | | |(3,10+$1*4)
+zer !defined($1)| X_CXREG |
+                       remove(ALL)
+                       move({ANYCON,0},bx)
+                       "sar cx,1"
+                       "1:\tpush bx"
+                       "loop 1b"
+                       samecc erase(%[1])                | | |
+
+lol adi stl $1==$3 && $2==2 | regorconst |
+                       remove(indexed)
+                       remove(locals, %[ind]>=$1 && %[ind]<$1+2 )
+                       "add $1(bp),%[1]"
+                       setcc({LOCAL2, $1, 2})            | | |
+lol ngi stl $1==$3 && $2==2 | |
+                       remove(indexed)
+                       remove(locals, %[ind]>=$1 && %[ind]<$1+2 )
+                       "neg $1(bp)"
+                       setcc({LOCAL2, $1, 2})            | | |
+lol ads stl $1==$3 && $2==2 | regorconst |
+                       remove(indexed)
+                       remove(locals, %[ind]>=$1 && %[ind]<$1+2 )
+                       "add $1(bp),%[1]"
+                       setcc({LOCAL2, $1, 2})            | | |
+lol adp stl $1==$3         | |
+                       remove(indexed)
+                       remove(locals, %[ind]>=$1 && %[ind]<$1+2 )
+                       "add $1(bp),$2"
+                       setcc({LOCAL2, $1, 2})            | | |
+lol adp stl $1==$3 && $2==1 | |
+                       remove(indexed)
+                       remove(locals, %[ind]>=$1 && %[ind]<$1+2 )
+                       "inc $1(bp)"
+                       setcc({LOCAL2, $1, 2})            | | |
+lol adp stl $1==$3 && $2==0-1 | |
+                       remove(indexed)
+                       remove(locals, %[ind]>=$1 && %[ind]<$1+2 )
+                       "dec $1(bp)"
+                       setcc({LOCAL2, $1, 2})            | | |
+lol and stl $1==$3 && $2==2 | regorconst |
+                       remove(indexed)
+                       remove(locals, %[ind]>=$1 && %[ind]<$1+2 )
+                       "and $1(bp),%[1]"
+                       setcc({LOCAL2, $1, 2})            | | |
+lol ior stl $1==$3 && $2==2 | regorconst |
+                       remove(indexed)
+                       remove(locals, %[ind]>=$1 && %[ind]<$1+2 )
+                       "or $1(bp),%[1]"
+                       setcc({LOCAL2, $1, 2})            | | |
+lol com stl $1==$3 && $2==2 | |
+                       remove(indexed)
+                       remove(locals, %[ind]>=$1 && %[ind]<$1+2 )
+                       "not $1(bp)"
+                       samecc                            | | |
+lil adi sil $1==$3 && $2==2 | regorconst |
+                       allocate(ADDREG={LOCAL2, $1, 2})
+                       remove(referals)
+                       "add (%[a]),%[1]"
+                       setcc({ind_reg2, %[a]})           | | |
+lil ngi sil $1==$3 && $2==2 | |
+                       allocate(ADDREG={LOCAL2, $1, 2})
+                       remove(referals)
+                       "neg (%[a])"
+                       setcc({ind_reg2, %[a]})           | | |
+lil ads sil $1==$3 && $2==2 | regorconst |
+                       allocate(ADDREG={LOCAL2, $1, 2})
+                       remove(referals)
+                       "add (%[a]),%[1]"
+                       setcc({ind_reg2, %[a]})           | | |
+lil adp sil $1==$3         | |
+                       allocate(ADDREG={LOCAL2, $1, 2})
+                       remove(referals)
+                       "add (%[a]),$2"
+                       setcc({ind_reg2, %[a]})           | | |
+lil adp sil $1==$3 && $2==1 | |
+                       allocate(ADDREG={LOCAL2, $1, 2})
+                       remove(referals)
+                       "inc (%[a])"
+                       setcc({ind_reg2, %[a]})           | | |
+lil adp sil $1==$3 && $2==0-1 | |
+                       allocate(ADDREG={LOCAL2, $1, 2})
+                       remove(referals)
+                       "dec (%[a])"
+                       setcc({ind_reg2, %[a]})           | | |
+lil and sil $1==$3 && $2==2 | regorconst |
+                       allocate(ADDREG={LOCAL2, $1, 2})
+                       remove(referals)
+                       "and (%[a]),%[1]"
+                       setcc({ind_reg2, %[a]})           | | |
+lil ior sil $1==$3 && $2==2 | regorconst |
+                       allocate(ADDREG={LOCAL2, $1, 2})
+                       remove(referals)
+                       "or (%[a]),%[1]"
+                       setcc({ind_reg2, %[a]})           | | |
+lil com sil $1==$3 && $2==2 | |
+                       allocate(ADDREG={LOCAL2, $1, 2})
+                       remove(referals)
+                       "not (%[a])"
+                       samecc                            | | |
+loe adi ste $1==$3 && $2==2 | regorconst |
+                       remove(indirects)
+                       "add ($1),%[1]"
+                       setcc({EXTERN2, $1})              | | |
+loe ngi ste $1==$3 && $2==2 | |
+                       remove(indirects)
+                       "neg ($1)"
+                       setcc({EXTERN2, $1})              | | |
+loe ads ste $1==$3 && $2==2 | regorconst |
+                       remove(indirects)
+                       "add ($1),%[1]"
+                       setcc({EXTERN2, $1})              | | |
+loe adp ste $1==$3         | |
+                       remove(indirects)
+                       "add ($1),$2"
+                       setcc({EXTERN2, $1})              | | |
+loe adp ste $1==$3 && $2==1 | |
+                       remove(indirects)
+                       "inc ($1)"
+                       setcc({EXTERN2, $1})              | | |
+loe adp ste $1==$3 && $2==0-1 | |
+                       remove(indirects)
+                       "dec ($1)"
+                       setcc({EXTERN2, $1})              | | |
+loe and ste $1==$3 && $2==2 | regorconst |
+                       remove(indirects)
+                       "and ($1),%[1]"
+                       setcc({EXTERN2, $1})              | | |
+loe ior ste $1==$3 && $2==2 | regorconst |
+                       remove(indirects)
+                       "or ($1),%[1]"
+                       setcc({EXTERN2, $1})              | | |
+loe com ste $1==$3 && $2==2 | |
+                       remove(indirects)
+                       "not ($1)"
+                       samecc                            | | |
+
+/****************************************
+ * Group 8 : Convert instructions      *
+ ****************************************/
+
+cii            | CXREG DXREG X_ACC |
+                       remove(ALL)
+                       "call .cii"
+                       erase(%[3])                  | %[3] | |
+ciu            | |             |                       | cuu   |
+cui            | |             |                       | cuu   |
+cuu            | CXREG BXREG X_ACC |
+                       remove(ALL)
+                       "call .cuu"
+                       erase(%[3])                  | %[3] | |
+cif            | CXREG DXREG |
+                       remove(ALL)
+                       "call .cif"                       | | |
+cuf            | CXREG DXREG |
+                       remove(ALL)
+                       "call .cuf"                       | | |
+cfi            | CXREG DXREG |
+                       remove(ALL)
+                       "call .cfi"                       | | |
+cfu            | CXREG DXREG |
+                       remove(ALL)
+                       "call .cfu"                       | | |
+cff            | CXREG DXREG |
+                       remove(ALL)
+                       "call .cff"                       | | |
+loc loc cii $1==1 && $2==2     | ACC1 |
+                        allocate(%[1],ACC)
+                        "cbw"
+                        samecc                     | %[a]  | |(1,2)
+loc loc cii $1==1 && $2==4     | ACC1 |
+                       allocate(%[1],ACC,DXREG)
+                       "cbw"
+                       "cwd"
+                       samecc                      | dx ax | |(2,7)
+loc loc cii $1==2 && $2==4     | ACC |
+                       allocate(DXREG)
+                       "cwd"
+                       samecc                      | dx ax | |(1,5)
+loc loc cii $1==4 && $2==2     | a_word a_word |    | %[1] | |
+loc loc cuu $1==2 && $2==4     | a_word |
+                       allocate(REG={ANYCON,0})| %[a] %[1] | |
+loc loc cuu $1==4 && $2==2     | a_word a_word |    | %[1] | |
+loc loc ciu $1==2 && $2==4     | a_word |
+                       allocate(REG={ANYCON,0})| %[a] %[1] | |
+loc loc ciu $1==4 && $2==2     | a_word a_word |    | %[1] | |
+loc loc cui $1==2 && $2==4     | a_word |
+                       allocate(REG={ANYCON,0})| %[a] %[1] | |
+loc loc cui $1==4 && $2==2     | a_word a_word |    | %[1] | |
+
+/****************************************
+ * Group 9 : Logical instructions      *
+ ****************************************/
+
+and $1==2      | NO X_REG rmorconst |
+                       "and %[1],%[2]"
+                       erase(%[1]) setcc(%[1]) | %[1]  | | (2,3) + %[2]
+...            | rmorconst X_REG |
+                       "and %[2],%[1]"
+                       erase(%[2]) setcc(%[2]) | %[2]  | | (2,3) + %[1]
+...            | X_ACC const |
+                       "and %[1],%[2]"
+                       erase(%[1]) setcc(%[1]) | %[1]  | | (3,4)
+...            | const X_ACC |
+                       "and %[2],%[1]"
+                       erase(%[2]) setcc(%[2]) | %[2]  | | (3,4)
+and $1==4      | NO X_REG X_REG rmorconst rmorconst |
+                       "and %[1],%[3]"
+                       "and %[2],%[4]"
+                       setcc(%[2]) erase(%[1]) erase(%[2])
+                                               | %[2] %[1] | |(4,6)+%[4]+%[3]
+...            | X_ACC X_REG const rmorconst |
+                       "and %[1],%[3]"
+                       "and %[2],%[4]"
+                       setcc(%[2]) erase(%[1]) erase(%[2])
+                                               | %[2] %[1] | |(5,7)+%[4]
+...            | rmorconst rmorconst X_REG X_REG |
+                       "and %[3],%[1]"
+                       "and %[4],%[2]"
+                       setcc(%[4]) erase(%[3]) erase(%[4])
+                                               | %[4] %[3] | |(4,6)+%[1]+%[2]
+...            | const rmorconst-ACC X_ACC X_REG |
+                       "and %[3],%[1]"
+                       "and %[4],%[2]"
+                       setcc(%[4]) erase(%[3]) erase(%[4])
+                                               | %[4] %[3] | |(5,7)+%[2]
+and defined($1) | |    remove(ALL)
+                       "mov cx,$1"
+                       "call .and"                       | | |
+and !defined($1)| X_CXREG |
+                       remove(ALL)
+                       "call .and"
+                       erase(%[1])                       | | |
+ior $1==2      | X_REG rmorconst |
+                       "or %[1],%[2]"
+                       erase(%[1]) setcc(%[1]) | %[1]  | | (2,3) + %[2]
+...            | NO rmorconst X_REG |
+                       "or %[2],%[1]"
+                       erase(%[2]) setcc(%[2]) | %[2]  | | (2,3) + %[1]
+...            | X_ACC const |
+                       "or %[1],%[2]"
+                       erase(%[1]) setcc(%[1]) | %[1]  | | (3,4)
+...            | const X_ACC |
+                       "or %[2],%[1]"
+                       erase(%[2]) setcc(%[2]) | %[2]  | | (3,4)
+ior $1==4      | NO X_REG X_REG rmorconst rmorconst |
+                       "or %[1],%[3]"
+                       "or %[2],%[4]"
+                       setcc(%[2]) erase(%[1]) erase(%[2])
+                                               | %[2] %[1] | |(4,6)+%[4]+%[3]
+...            | X_ACC X_REG const rmorconst |
+                       "or %[1],%[3]"
+                       "or %[2],%[4]"
+                       setcc(%[2]) erase(%[1]) erase(%[2])
+                                               | %[2] %[1] | |(5,7)+%[4]
+...            | rmorconst rmorconst X_REG X_REG |
+                       "or %[3],%[1]"
+                       "or %[4],%[2]"
+                       setcc(%[4]) erase(%[3]) erase(%[4])
+                                               | %[4] %[3] | |(4,6)+%[1]+%[2]
+...            | const rmorconst-ACC X_ACC X_REG |
+                       "or %[3],%[1]"
+                       "or %[4],%[2]"
+                       setcc(%[4]) erase(%[3]) erase(%[4])
+                                               | %[4] %[3] | |(5,7)+%[2]
+ior defined($1) | |    remove(ALL)
+                       "mov cx,$1"
+                       "call .ior"                       | | |
+ior !defined($1)| X_CXREG |
+                       remove(ALL)
+                       "call .ior"
+                       erase(%[1])                       | | |
+xor $1==2      | NO X_REG rmorconst |
+                       "xor %[1],%[2]"
+                       erase(%[1]) setcc(%[1]) | %[1]  | | (2,3) + %[2]
+...            | rmorconst X_REG |
+                       "xor %[2],%[1]"
+                       erase(%[2]) setcc(%[2]) | %[2]  | | (2,3) + %[1]
+...            | X_ACC const |
+                       "xor %[1],%[2]"
+                       erase(%[1]) setcc(%[1]) | %[1]  | | (3,4)
+...            | const X_ACC |
+                       "xor %[2],%[1]"
+                       erase(%[2]) setcc(%[2]) | %[2]  | | (3,4)
+xor $1==4      | NO X_REG X_REG rmorconst rmorconst |
+                       "xor %[1],%[3]"
+                       "xor %[2],%[4]"
+                       setcc(%[2]) erase(%[1]) erase(%[2])
+                                               | %[2] %[1] | |(4,6)+%[4]+%[3]
+...            | X_ACC X_REG const rmorconst |
+                       "xor %[1],%[3]"
+                       "xor %[2],%[4]"
+                       setcc(%[2]) erase(%[1]) erase(%[2])
+                                               | %[2] %[1] | |(5,7)+%[4]
+...            | rmorconst rmorconst X_REG X_REG |
+                       "xor %[3],%[1]"
+                       "xor %[4],%[2]"
+                       setcc(%[4]) erase(%[3]) erase(%[4])
+                                               | %[4] %[3] | |(4,6)+%[1]+%[2]
+...            | const rmorconst-ACC X_ACC X_REG |
+                       "xor %[3],%[1]"
+                       "xor %[4],%[2]"
+                       setcc(%[4]) erase(%[3]) erase(%[4])
+                                               | %[4] %[3] | |(5,7)+%[2]
+xor defined($1) | |    remove(ALL)
+                       "mov cx,$1"
+                       "call .xor"                       | | |
+xor !defined($1)| X_CXREG |
+                       remove(ALL)
+                       "call .xor"
+                       erase(%[1])                       | | |
+com $1==2      | X_REG |
+                       "not %[1]"
+                       samecc erase(%[1])          | %[1]  | |(2,3)
+com $1==4      | X_REG X_REG |
+                       "not %[2]"
+                       "not %[1]"
+                       samecc erase(%[1]) erase(%[2])
+                                               | %[2] %[1] | |(4,6)
+com defined($1) | |    remove(ALL)
+                       "mov cx,$1"
+                       "call .com"                       | | |
+com !defined($1)| X_CXREG |
+                       remove(ALL)
+                       "call .com"
+                       erase(%[1])                       | | |
+loc rol $1==1 && $2==2 | X_REG |
+                       "rol %[1],1"
+                       samecc erase(%[1])           | %[1] | | (2,2)
+rol $1==2      | SHIFT_CREG X_REG |
+                       "rol %[2],cl"
+                       samecc erase(%[2])           | %[2] | | (2,8)
+rol $1==4      | X_CXREG X_REG X_REG |
+                       "jcxz 1f"
+                       "2: sal %[2],1"
+                       "rcl %[3],1"
+                       "adc %[2],0"
+                       "loop 2b\n1:"
+                       erase(%[1]) erase(%[2]) erase(%[3])
+                                               | %[3] %[2] | |
+/*
+rol !defined($1)| X_CXREG |
+                       remove(ALL)
+                       "call .rol"                 |       | |
+*/
+loc ror $1==1 && $2==2 | X_REG |
+                       "ror %[1],1"
+                       samecc erase(%[1])           | %[1] | | (2,2)
+ror $1==2      | SHIFT_CREG X_REG |
+                       "ror %[2],cl"
+                       samecc erase(%[2])           | %[2] | | (2,8)
+ror $1==4      | X_CXREG X_REG X_REG |
+                       "jcxz 1f"
+                       "neg cx"
+                       "add cx,32"
+                       "2: sal %[2],1"
+                       "rcl %[3],1"
+                       "adc %[2],0"
+                       "loop 2b\n1:"
+                       erase(%[1]) erase(%[2]) erase(%[3])
+                                               | %[3] %[2] | |
+/*
+ror !defined($1)| X_CXREG |
+                       remove(ALL)
+                       "call .ror"                 |       | |
+*/
+
+/********************************
+ * Group 10 : Set instructions *
+ ********************************/
+
+inn $1==2      | SHIFT_CREG X_REG |
+                       "shr %[2],cl"
+                       "and %[2],1"
+                       setcc(%[2]) erase(%[2])      | %[2] | |(6,13)
+...            | SHIFT_CREG X_ACC |
+                       "shr %[2],cl"
+                       "and %[2],1"
+                       setcc(%[2]) erase(%[2])      | %[2] | |(5,13)
+loc inn $1==1 && $2==2 | X_REG |
+                       "shr %[1],1"
+                       "and %[1],1"
+                       setcc(%[1]) erase(%[1])      | %[1] | |(6,6)
+...                | X_ACC |
+                       "shr %[1],1"
+                       "and %[1],1"
+                       setcc(%[1]) erase(%[1])      | %[1] | |(5,6)
+loc inn $1==0 && $2==2 | X_REG |
+                       "and %[1],1"
+                       setcc(%[1]) erase(%[1])      | %[1] | |(6,6)
+...                | X_ACC |
+                       "and %[1],1"
+                       setcc(%[1]) erase(%[1])      | %[1] | |(5,6)
+inn defined($1) | X_ACC |
+                       remove(ALL)
+                       move({ANYCON,$1},cx)
+                       "call .inn"
+                       erase(ax)                      | ax | |
+inn !defined($1)| CXREG X_ACC |
+                       remove(ALL)
+                       "call .inn"
+                       erase(%[2])                    | ax | |
+loc inn zeq $2==2 | rm |
+                       remove(ALL)
+                       "test %[1],%(1<<$1%)"
+                       "je $3"                        |    | |
+loc inn zne $2==2 | rm |
+                       remove(ALL)
+                       "test %[1],%(1<<$1%)"
+                       "jne $3"                       |    | |
+set $1==2      | SHIFT_CREG |
+                       allocate(REG={ANYCON,1})
+                       "shl %[a],cl"
+                       setcc(%[a]) erase(%[a])        | %[a] | |
+set defined($1) | X_ACC |
+                       remove(ALL)
+                       move({ANYCON,$1},cx)
+                       "call .set"
+                       erase(%[1])                    |      | |
+set !defined($1)| CXREG X_ACC |
+                       remove(ALL)
+                       "call .set"
+                       erase(%[2])                    |      | |
+
+/****************************************
+ * Group 11 : Array instructions       *
+ ****************************************/
+
+lae aar $2==2 && rom(1,3)==1 && rom(1,1)==0 | | | | ads 2 |
+lae aar $2==2 && rom(1,3)==1 && rom(1,1)!=0 | | | | adp 0-rom(1,1) ads 2 |
+lae aar $2==2 && rom(1,3)==2 && rom(1,1)==0 | X_ADDREG |
+                       "sal %[1],1"
+                       erase(%[1])        | %[1] | ads 2 |
+lae aar $2==2 && rom(1,3)==2 && rom(1,1)!=0 | X_ADDREG |
+                       "sal %[1],1"
+                       erase(%[1])        | %[1] | adp 0-2*rom(1,1) ads 2 |
+lae aar $2==2 && rom(1,3)==4 && rom(1,1)==0 | X_ADDREG |
+                       "sal %[1],1"
+                       "sal %[1],1"
+                       erase(%[1])        | %[1] | ads 2 |
+lae aar $2==2 && rom(1,3)==4 && rom(1,1)!=0 | X_ADDREG |
+                       "sal %[1],1"
+                       "sal %[1],1"
+                       erase(%[1])        | %[1] | adp 0-4*rom(1,1) ads 2 |
+lae aar $2==2 && rom(1,1)==0               | X_ACC |
+                       allocate(DXREG,REG={ANYCON,rom(1,3)})
+                       "mul %[b]"
+                       erase(%[1])         | %[1] | ads 2 |
+lae aar $2==2 && defined(rom(1,1))         | X_ACC |
+                       allocate(DXREG,REG={ANYCON,rom(1,3)})
+                       "mul %[b]"
+                       erase(%[1])  | %[1] | adp 0-rom(1,1)*rom(1,3) ads 2 |
+aar $1==2       | halfindir X_ACC X_ADDREG |
+                       allocate(DXREG)
+                       "sub %[2],%[1]"
+                       "mul 4+%[1]"
+                       "add %[3],%[2]"
+                       erase(%[2]) erase(%[3])
+                                           | %[3] | |
+...            | ADDR_EXTERN X_ACC X_ADDREG |
+                       allocate(DXREG)
+                       "sub %[2],(%[1])"
+                       "mul (4+%[1])"
+                       "add %[3],%[2]"
+                       erase(%[2]) erase(%[3])
+                                           | %[3] | |
+lae sar defined(rom(1,3)) | |  |       | lae $1 aar $2 sti rom(1,3) |
+lae lar defined(rom(1,3)) | |  |       | lae $1 aar $2 loi rom(1,3) |
+aar !defined($1) | |   remove(ALL)
+                       "call .iaar"        | di | |
+sar $1==2      | X_SIREG X_ACC X_DIREG |
+                       remove(ALL)
+                       "call .sar2"
+                       erase(%[1]) erase(%[2]) erase(%[3])
+                                                | | |
+sar !defined($1) | |   remove(ALL)
+                       "call .isar"           | | |
+lar $1==2      | X_DIREG X_ACC X_SIREG |
+                       remove(ALL)
+                       "call .lar2"
+                       erase(%[1]) erase(%[2]) erase(%[3])
+                                                | | |
+lar !defined($1) | |   remove(ALL)
+                       "call .ilar"           | | |
+
+/****************************************
+ * group 12 : Compare instructions     *
+ ****************************************/
+
+cmi $1==2      | |     |                                   | sbi 2  |
+cmi $1==4      | rmorconst rmorconst X_REG X_REG |
+                       "sub %[3],%[1]"
+                       "sbb %[4],%[2]"
+                       "jne 1f"
+                       "and %[3],%[3]"
+                       "je 1f"
+                       "inc %[4]\n1: "
+                       setcc(%[4]) erase(%[3]) erase(%[4])
+                                                    | %[4] | |
+cmu $1==2      | |     |                                   | cmp |
+cmu $1==4      | |     remove(ALL)
+                       "call .cmu4"                   | ax | |
+cms $1==2      | NO X_REG rmorconst |
+                       "sub %[1],%[2]"
+                       erase(%[1]) setcc(%[1]) |      %[1] | | (2,3) + %[2]
+...            | rmorconst X_REG |
+                       "sub %[2],%[1]"
+                       erase(%[2]) setcc(%[2]) |      %[2] | | (2,3) + %[1]
+...            | X_ACC const |
+                       "sub %[1],%[2]"
+                       erase(%[1]) setcc(%[1]) |      %[1] | | (3,4)
+...            | const X_ACC |
+                       "sub %[2],%[1]"
+                       erase(%[2]) setcc(%[2]) |      %[2] | | (3,4)
+cms $1==4      | rmorconst rmorconst X_REG X_REG |
+                       "sub %[3],%[1]"
+                       "sbb %[4],%[2]"
+                       "jne 1f"
+                       "or %[4],%[3]\n1: "
+                       setcc(%[4]) erase(%[3]) erase(%[4])
+                                                    | %[4] | |
+...            | NO X_REG X_REG rmorconst rmorconst |
+                       "sub %[1],%[3]"
+                       "sbb %[2],%[4]"
+                       "jne 1f"
+                       "or %[2],%[1]\n1: "
+                       setcc(%[2]) erase(%[1]) erase(%[2])
+                                                    | %[2] | |
+cms defined($1) | |    remove(ALL)
+                       move({ANYCON,$1},cx)
+                       "call .cms"
+                       erase(cx)                      | cx | |
+cms !defined($1)| X_CXREG |
+                       remove(ALL)
+                       "call .cms"
+                       erase(cx)                      | cx | |
+cmf $1==4      | |
+                       remove(ALL)
+                       "call .cmf4"                |       | |
+cmf $1==8      | |
+                       remove(ALL)
+                       "call .cmf8"                |       | |
+cmf !defined($1)       | X_CXREG |
+                       remove(ALL)
+                       "call .cmf" erase(%[1])     |       | |
+
+/* The costs with cmp are the cost of the 8086 cmp instruction */
+cmp            | NO REG rmorconst |
+                       allocate(REG = {ANYCON,0})
+                       "cmp %[1],%[2]"
+                       "je 2f"
+                       "jb 1f"
+                       "inc %[a]"
+                       "jmp 2f"
+                       "1:\tdec %[a]\n2:"
+                       setcc(%[a])
+                       erase(%[a])                  | %[a] | |(4,4)
+...           | rmorconst REG |
+                       allocate(REG = {ANYCON,0})
+                       "cmp %[1],%[2]"
+                       "je 2f"
+                       "jb 1f"
+                       "inc %[a]"
+                       "jmp 2f"
+                       "1:\tdec %[a]\n2:"
+                       setcc(%[a])
+                       erase(%[a])                  | %[a] | |(4,4)
+...           | ACC const |
+                       allocate(REG = {ANYCON,0})
+                       "cmp %[1],%[2]"
+                       "je 2f"
+                       "jb 1f"
+                       "inc %[a]"
+                       "jmp 2f"
+                       "1:\tdec %[a]\n2:"
+                       setcc(%[a])
+                       erase(%[a])                  | %[a] | |(3,4)
+...           | const ACC |
+                       allocate(REG = {ANYCON,0})
+                       "cmp %[1],%[2]"
+                       "je 2f"
+                       "jb 1f"
+                       "inc %[a]"
+                       "jmp 2f"
+                       "1:\tdec %[a]\n2:"
+                       setcc(%[a])
+                       erase(%[a])                  | %[a] | |(3,4)
+tlt            | rm |
+                       allocate(REG={ANYCON,0})
+                       test(%[1])
+                       "jge 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+tle            | rm |
+                       allocate(REG={ANYCON,0})
+                       test(%[1])
+                       "jg 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+teq            | rm |
+                       allocate(REG={ANYCON,0})
+                       test(%[1])
+                       "jne 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+tne            | rm |
+                       allocate(REG={ANYCON,0})
+                       test(%[1])
+                       "je 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+tge            | rm |
+                       allocate(REG={ANYCON,0})
+                       test(%[1])
+                       "jl 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+tgt            | rm |
+                       allocate(REG={ANYCON,0})
+                       test(%[1])
+                       "jle 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+tlt ior $2==2  | rm X_REG |
+                       test(%[1])
+                       "jge 1f"
+                       "or %[2],1\n1:"
+                       erase(%[2])                  | %[2] | |
+tle ior $2==2  | rm X_REG |
+                       test(%[1])
+                       "jg 1f"
+                       "or %[2],1\n1:"
+                       erase(%[2])                  | %[2] | |
+teq ior $2==2  | rm X_REG |
+                       test(%[1])
+                       "jne 1f"
+                       "or %[2],1\n1:"
+                       erase(%[2])                  | %[2] | |
+tne ior $2==2  | rm X_REG |
+                       test(%[1])
+                       "je 1f"
+                       "or %[2],1\n1:"
+                       erase(%[2])                  | %[2] | |
+tge ior $2==2  | rm X_REG |
+                       test(%[1])
+                       "jl 1f"
+                       "or %[2],1\n1:"
+                       erase(%[2])                  | %[2] | |
+tgt ior $2==2  | rm X_REG |
+                       test(%[1])
+                       "jle 1f"
+                       "or %[2],1\n1:"
+                       erase(%[2])                  | %[2] | |
+cmi tlt ior $1==2 && $3==2     | regorconst rm X_REG |
+                       "cmp %[2],%[1]"
+                       "jge 1f"
+                       "or %[3],1\n1:"
+                       erase(%[3])                  | %[3] | |
+cmi tle ior $1==2 && $3==2     | regorconst rm X_REG |
+                       "cmp %[2],%[1]"
+                       "jg 1f"
+                       "or %[3],1\n1:"
+                       erase(%[3])                  | %[3] | |
+cmi teq ior $1==2 && $3==2     | regorconst rm X_REG |
+                       "cmp %[2],%[1]"
+                       "jne 1f"
+                       "or %[3],1\n1:"
+                       erase(%[3])                  | %[3] | |
+cmi tne ior $1==2 && $3==2     | regorconst rm X_REG |
+                       "cmp %[2],%[1]"
+                       "je 1f"
+                       "or %[3],1\n1:"
+                       erase(%[3])                  | %[3] | |
+cmi tge ior $1==2 && $3==2     | regorconst rm X_REG |
+                       "cmp %[2],%[1]"
+                       "jl 1f"
+                       "or %[3],1\n1:"
+                       erase(%[3])                  | %[3] | |
+cmi tgt ior $1==2 && $3==2     | regorconst rm X_REG |
+                       "cmp %[2],%[1]"
+                       "jle 1f"
+                       "or %[3],1\n1:"
+                       erase(%[3])                  | %[3] | |
+/* The cmp instruction has a special form for comparing
+   a byte ( sign-extended ) to a word (e.g. a register)
+   The "cmp ax,0" and "cmp bx,0" instructions have widely different
+   encodings but take the same amount of time and space.
+   Conclusion, using the special instruction for comparing
+   constants with ax is only better when the constant is <-128 or >127.
+   This relatively rare event wasn't worth extra entries in this table.
+*/
+cmi tlt $1==2  | regorconst rm |
+                       allocate(REG={ANYCON,0})
+                       "cmp %[2],%[1]"
+                       "jge 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+...            | NO rm regorconst |
+                       allocate(REG={ANYCON,0})
+                       "cmp %[1],%[2]"
+                       "jle 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+cmi tle $1==2  | regorconst rm |
+                       allocate(REG={ANYCON,0})
+                       "cmp %[2],%[1]"
+                       "jg 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+...            | NO rm regorconst |
+                       allocate(REG={ANYCON,0})
+                       "cmp %[1],%[2]"
+                       "jl 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+cmi teq $1==2  | regorconst rm |
+                       allocate(REG={ANYCON,0})
+                       "cmp %[2],%[1]"
+                       "jne 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+...            | NO rm regorconst |
+                       allocate(REG={ANYCON,0})
+                       "cmp %[1],%[2]"
+                       "jne 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+cmi tne $1==2  | regorconst rm |
+                       allocate(REG={ANYCON,0})
+                       "cmp %[2],%[1]"
+                       "je 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+...            | NO rm regorconst |
+                       allocate(REG={ANYCON,0})
+                       "cmp %[1],%[2]"
+                       "je 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+cmi tge $1==2  | regorconst rm |
+                       allocate(REG={ANYCON,0})
+                       "cmp %[2],%[1]"
+                       "jl 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+...            | NO rm regorconst |
+                       allocate(REG={ANYCON,0})
+                       "cmp %[1],%[2]"
+                       "jg 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+cmi tgt $1==2  | regorconst rm |
+                       allocate(REG={ANYCON,0})
+                       "cmp %[2],%[1]"
+                       "jle 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+...            | NO rm regorconst |
+                       allocate(REG={ANYCON,0})
+                       "cmp %[1],%[2]"
+                       "jge 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+cmp tlt        | regorconst rm |
+                       allocate(REG={ANYCON,0})
+                       "cmp %[2],%[1]"
+                       "jae 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+...            | NO rm regorconst |
+                       allocate(REG={ANYCON,0})
+                       "cmp %[1],%[2]"
+                       "jbe 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+cmp tle        | regorconst rm |
+                       allocate(REG={ANYCON,0})
+                       "cmp %[2],%[1]"
+                       "ja 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+...            | NO rm regorconst |
+                       allocate(REG={ANYCON,0})
+                       "cmp %[1],%[2]"
+                       "jb 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+cmp teq        | regorconst rm |
+                       allocate(REG={ANYCON,0})
+                       "cmp %[2],%[1]"
+                       "jne 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+...            | NO rm regorconst |
+                       allocate(REG={ANYCON,0})
+                       "cmp %[1],%[2]"
+                       "jne 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+cmp tne        | regorconst rm |
+                       allocate(REG={ANYCON,0})
+                       "cmp %[2],%[1]"
+                       "je 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+...            | NO rm regorconst |
+                       allocate(REG={ANYCON,0})
+                       "cmp %[1],%[2]"
+                       "je 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+cmp tge        | regorconst rm |
+                       allocate(REG={ANYCON,0})
+                       "cmp %[2],%[1]"
+                       "jb 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+...            | NO rm regorconst |
+                       allocate(REG={ANYCON,0})
+                       "cmp %[1],%[2]"
+                       "ja 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+cmp tgt        | regorconst rm |
+                       allocate(REG={ANYCON,0})
+                       "cmp %[2],%[1]"
+                       "jbe 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+...            | NO rm regorconst |
+                       allocate(REG={ANYCON,0})
+                       "cmp %[1],%[2]"
+                       "jae 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+cms teq $1==2  | regorconst rm |
+                       allocate(REG={ANYCON,0})
+                       "cmp %[2],%[1]"
+                       "jne 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+...            | NO rm regorconst |
+                       allocate(REG={ANYCON,0})
+                       "cmp %[1],%[2]"
+                       "jne 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+cms tne $1==2  | regorconst rm |
+                       allocate(REG={ANYCON,0})
+                       "cmp %[2],%[1]"
+                       "je 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+...            | NO rm regorconst |
+                       allocate(REG={ANYCON,0})
+                       "cmp %[1],%[2]"
+                       "je 1f"
+                       "inc %[a]\n1:"
+                       erase(%[a])                  | %[a] | |
+cmp zlt        | regorconst rm |
+                       remove(ALL)
+                       "cmp %[2],%[1]"
+                       "jb $2"                           | | |
+...            | NO rm regorconst |
+                       remove(ALL)
+                       "cmp %[1],%[2]"
+                       "ja $2"                           | | |
+cmp zle        | regorconst rm |
+                       remove(ALL)
+                       "cmp %[2],%[1]"
+                       "jbe $2"                          | | |
+...            | NO rm regorconst |
+                       remove(ALL)
+                       "cmp %[1],%[2]"
+                       "jae $2"                          | | |
+cmp zeq        | regorconst rm |
+                       remove(ALL)
+                       "cmp %[2],%[1]"
+                       "je $2"                           | | |
+...            | NO rm regorconst |
+                       remove(ALL)
+                       "cmp %[1],%[2]"
+                       "je $2"                           | | |
+cmp zne        | regorconst rm |
+                       remove(ALL)
+                       "cmp %[2],%[1]"
+                       "jne $2"                          | | |
+...            | NO rm regorconst |
+                       remove(ALL)
+                       "cmp %[1],%[2]"
+                       "jne $2"                          | | |
+cmp zge        | regorconst rm |
+                       remove(ALL)
+                       "cmp %[2],%[1]"
+                       "jae $2"                          | | |
+...            | NO rm regorconst |
+                       remove(ALL)
+                       "cmp %[1],%[2]"
+                       "jbe $2"                          | | |
+cmp zgt        | regorconst rm |
+                       remove(ALL)
+                       "cmp %[2],%[1]"
+                       "ja $2"                           | | |
+...            | NO rm regorconst |
+                       remove(ALL)
+                       "cmp %[1],%[2]"
+                       "jb $2"                           | | |
+cms zeq $1==2  | regorconst rm |
+                       remove(ALL)
+                       "cmp %[2],%[1]"
+                       "je $2"                           | | |
+...            | NO rm regorconst |
+                       remove(ALL)
+                       "cmp %[1],%[2]"
+                       "je $2"                           | | |
+cms zne $1==2  | regorconst rm |
+                       remove(ALL)
+                       "cmp %[2],%[1]"
+                       "jne $2"                          | | |
+...            | NO rm regorconst |
+                       remove(ALL)
+                       "cmp %[1],%[2]"
+                       "jne $2"                          | | |
+and zeq $1==2  | regorconst rm |
+                       remove(ALL)
+                       "test %[2],%[1]"
+                       "je $2"                           | | |
+...            | NO rm regorconst |
+                       remove(ALL)
+                       "test %[1],%[2]"
+                       "je $2"                           | | |
+and zne $1==2  | regorconst rm |
+                       remove(ALL)
+                       "test %[2],%[1]"
+                       "jne $2"                          | | |
+...            | NO rm regorconst |
+                       remove(ALL)
+                       "test %[1],%[2]"
+                       "jne $2"                          | | |
+loc and zeq $1<256 && $1>=0 && $2==2           | nocoercions : rm1 + memory2 |
+                       remove(ALL)
+                       "testb %[1],$1"
+                       "je $3"                           | | | (1,3) + %[1]
+...                                            | GENREG |
+                       remove(ALL)
+                       "testb %[1.1],$1"
+                       "je $3"                           | | | (1,3) + %[1]
+...                                            | nocoercions : IREG |
+                       remove(ALL)
+                       "test %[1],$1"
+                       "je $3"                           | | | (2,3) + %[1]
+loc and zne $1<256 && $1>=0 && $2==2           | nocoercions : rm1 + memory2 |
+                       remove(ALL)
+                       "testb %[1],$1"
+                       "jne $3"                          | | | (1,3) + %[1]
+...                                            | GENREG |
+                       remove(ALL)
+                       "testb %[1.1],$1"
+                       "jne $3"                          | | | (1,3) + %[1]
+...                                            | nocoercions : IREG |
+                       remove(ALL)
+                       "test %[1],$1"
+                       "jne $3"                          | | | (2,3) + %[1]
+loc beq $1<256 && $1>=0                                | nocoercions : rm1 |
+                       remove(ALL)
+                       "cmpb %[1],$1"
+                       "je $2"                           | | | (1,3) + %[1]
+...                                            | rm |
+                       remove(ALL)
+                       "cmp %[1],$1"
+                       "je $2"                           | | | (2,3) + %[1]
+loc bne $1<256 && $1>=0                                | nocoercions : rm1 |
+                       remove(ALL)
+                       "cmpb %[1],$1"
+                       "jne $2"                          | | | (1,3) + %[1]
+...                                            | rm |
+                       remove(ALL)
+                       "cmp %[1],$1"
+                       "jne $2"                          | | | (2,3) + %[1]
+/* Note: test for <,<=,>,>= can be done in this way,
+        with use of the unsigned conditional jumps, jb, etc. */
+loc cmu zeq $1<256 && $1>=0 && $2==2           | nocoercions : rm1 |
+                       remove(ALL)
+                       "cmpb %[1],$1"
+                       "je $3"                           | | | (1,3) + %[1]
+...                                            | rm |
+                       remove(ALL)
+                       "cmp %[1],$1"
+                       "je $3"                           | | | (2,3) + %[1]
+loc cmu zne $1<256 && $1>=0 && $2==2           | nocoercions : rm1 |
+                       remove(ALL)
+                       "cmpb %[1],$1"
+                       "jne $3"                          | | | (1,3) + %[1]
+...                                            | rm |
+                       remove(ALL)
+                       "cmp %[1],$1"
+                       "jne $3"                          | | | (2,3) + %[1]
+
+/****************************************
+ * Group 13 : Branch instructions      *
+ ****************************************/
+
+bra            | |     remove(ALL)
+                       "jmp $1"
+                       samecc                            | | |
+blt            | regorconst rm |
+                       remove(ALL)
+                       "cmp %[2],%[1]"
+                       "jl $1"                           | | |
+...            | NO rm regorconst |
+                       remove(ALL)
+                       "cmp %[1],%[2]"
+                       "jg $1"                           | | |
+ble            | regorconst rm |
+                       remove(ALL)
+                       "cmp %[2],%[1]"
+                       "jle $1"                          | | |
+...            | NO rm regorconst |
+                       remove(ALL)
+                       "cmp %[1],%[2]"
+                       "jge $1"                          | | |
+beq            | regorconst rm |
+                       remove(ALL)
+                       "cmp %[2],%[1]"
+                       "je $1"                           | | |
+...            | NO rm regorconst |
+                       remove(ALL)
+                       "cmp %[1],%[2]"
+                       "je $1"                           | | |
+bne            | regorconst rm |
+                       remove(ALL)
+                       "cmp %[2],%[1]"
+                       "jne $1"                          | | |
+...            | NO rm regorconst |
+                       remove(ALL)
+                       "cmp %[1],%[2]"
+                       "jne $1"                          | | |
+bge            | regorconst rm |
+                       remove(ALL)
+                       "cmp %[2],%[1]"
+                       "jge $1"                          | | |
+...            | NO rm regorconst |
+                       remove(ALL)
+                       "cmp %[1],%[2]"
+                       "jle $1"                          | | |
+bgt            | regorconst rm |
+                       remove(ALL)
+                       "cmp %[2],%[1]"
+                       "jg $1"                           | | |
+...            | NO rm regorconst |
+                       remove(ALL)
+                       "cmp %[1],%[2]"
+                       "jl $1"                           | | |
+zlt            | rm |
+                       remove(ALL)
+                       test(%[1])
+                       "jl $1"                           | | |
+zle            | rm |
+                       remove(ALL)
+                       test(%[1])
+                       "jle $1"                          | | |
+zeq            | rm+rm1 |
+                       remove(ALL)
+                       test(%[1])
+                       "je $1"                           | | |
+zne            | rm+rm1 |
+                       remove(ALL)
+                       test(%[1])
+                       "jne $1"                          | | |
+zge            | rm |
+                       remove(ALL)
+                       test(%[1])
+                       "jge $1"                          | | |
+zgt            | rm |
+                       remove(ALL)
+                       test(%[1])
+                       "jg $1"                           | | |
+
+/************************************************
+ * group 14 : Procedure call instructions      *
+ ************************************************/
+
+cal            | |     remove(ALL)
+                       "call $1"                         | | |
+cai            | rm |  remove(ALL)
+                       "call %[1]"                       | | |
+lfr $1==2      | |                                    | ax | |
+lfr $1==4      | |                                 | dx ax | |
+lfr $1==6      | |                              | bx dx ax | |
+lfr $1==8      | |                           | cx bx dx ax | |
+ret $1==0      | |     remove(ALL)
+                       "mov sp,bp"
+                       "pop bp"
+                       "ret"                             | | |
+ret $1==2      | ACC |
+                       "mov sp,bp"
+                       "pop bp"
+                       "ret"                             | | |
+ret $1==4      | ACC DXREG |
+                       "mov sp,bp"
+                       "pop bp"
+                       "ret"                             | | |
+ret $1==6      | ACC DXREG BXREG |
+                       "mov sp,bp"
+                       "pop bp"
+                       "ret"                             | | |
+ret $1==8      | ACC DXREG BXREG CXREG |
+                       "mov sp,bp"
+                       "pop bp"
+                       "ret"                             | | |
+
+/************************************************
+ * Group 15 : Miscellaneous instructions       *
+ ************************************************/
+
+asp $1==2      | nocoercions : a_word |                  | | |
+...            | STACK |
+                       allocate(IREG) /* GENREG may contain lfr area */
+                       "pop %[a]" erase(%[a]) samecc     | | | (1,8)
+asp $1==4      | nocoercions : a_word a_word |           | | |
+...            | STACK |
+                       allocate(IREG) /* GENREG may contain lfr area */
+                       "pop %[a]" "pop %[a]"
+                       erase(%[a]) samecc                | | | (2,16)
+asp $1==0-2    | |     /* Anything will do */         | bp | |
+...            | |     remove(ALL)
+                       "push lb"                         | | | (1,10)
+asp            | |     remove(ALL)
+                       "add sp,$1"                       | | | (4,4)
+ass $1==2      | rmorconst |
+                       remove(ALL)
+                       "add sp,%[1]"                     | | |
+ass !defined($1)| rm rmorconst |
+                       remove(ALL)
+                       "cmp %[1],2"
+                       "jne .unknown"
+                       "add sp,%[2]"                     | | |
+blm $1==0      | |                                       | | asp 4 |
+blm $1>0       | X_DIREG X_SIREG |
+                       remove(ALL)
+                       allocate(CXREG={ANYCON,$1/2})
+                       "rep movs"
+                       erase(%[1]) erase(%[2]) erase(%[a])
+                                                         | | |
+bls $1==2      | X_CXREG X_DIREG X_SIREG |
+                       remove(ALL)
+                       "sar cx,1"
+                       "rep movs"
+                       erase(%[1]) erase(%[2]) erase(%[3])
+                                                         | | |
+bls !defined($1)| rm-CXREG-DIREG-SIREG X_CXREG X_DIREG X_SIREG |
+                       remove(ALL)
+                       "cmp %[1],2"
+                       "jne .unknown"
+                       "sar cx,1"
+                       "rep movs"
+                       erase(%[2]) erase(%[3]) erase(%[4])
+                                                         | | |
+csa $1==2      | X_SIREG X_BXREG |
+                       remove(ALL)
+                       "jmp .csa2"
+                       erase(%[1]) erase(%[2])           | | |
+csa !defined($1)| rm-SIREG-BXREG X_SIREG X_BXREG |
+                       remove(ALL)
+                       "cmp %[1],2"
+                       "jne .unknown"
+                       "jmp .csa2"
+                       erase(%[2]) erase(%[3])           | | |
+csb $1==2      | X_SIREG X_DXREG |
+                       remove(ALL)
+                       "jmp .csb2"
+                       erase(%[1]) erase(%[2])           | | |
+csb !defined($1)| rm-SIREG-DIREG X_SIREG X_DXREG |
+                       remove(ALL)
+                       "cmp %[1],2"
+                       "jne .unknown"
+                       "jmp .csb2"
+                       erase(%[2]) erase(%[3])           | | |
+dup $1==2      | REG |                         | %[1] %[1] | |
+dup $1==4      | REG REG |           | %[2] %[1] %[2] %[1] | |
+dup            | |     remove(ALL)
+                       move({ANYCON, $1}, cx)
+                       "call .dup"
+                       erase(cx)                         | | |
+dus $1==2      | X_CXREG |
+                       remove(ALL)
+                       "call .dup"
+                       erase(%[1])                       | | |
+dus !defined($1)| rm-CXREG X_CXREG |
+                       remove(ALL)
+                       "cmp %[1],2"
+                       "jne .unknown"
+                       "call .dup"
+                       erase(%[2])                       | | |
+exg $1==2      | a_word a_word |               | %[1] %[2] | |
+exg $1==4      | a_word a_word a_word a_word |
+                                     | %[2] %[1] %[4] %[3] | |
+exg defined($1) | |    remove(ALL)
+                       move({ANYCON,$1},cx)
+                       "call .exg"
+                       erase(cx)                         | | |
+exg            | rmorconst |
+                       remove(ALL)
+                       move(%[1],cx)
+                       "call .exg"
+                       erase(cx)                         | | |
+gto            | |     remove(ALL)
+                       "mov bx,$1"
+                       "jmp .gto"                        | | |
+fil            | |     "mov (hol0+4),$1"                 | | |
+lim            | |     allocate(REG)
+                       "mov %[a],(.ignmask)"        | %[a] | |
+lin            | |     "mov (hol0),$1"                   | | |
+lni            | |     "inc (hol0)"                      | | |
+lor $1==0      | |                                    | bp | |
+lor $1==1      | |     remove(ALL)
+                       allocate(REG)
+                       "mov %[a],sp"                | %[a] | |
+lor $1==2      | |     allocate(REG)
+                       "mov %[a],(.reghp)"          | %[a] | |
+mon            | X_ACC |
+                       remove(ALL)
+                       "call .mon"                       | | |
+nop            | |     remove(ALL)
+                       "call .nop"                       | | |
+rck $1==2      | SIREG ACC |
+                       "call .rck"                    | ax | |
+rck !defined($1)| rm-SIREG-ACC SIREG ACC |
+                       "cmp %[1],2"
+                       "jne .unknown"
+                       "call .rck"                    | ax | |
+rtt            | |             |                           | ret 0 |
+sig            | X_REG |
+                       "xchg (.trppc),%[1]"
+                       erase(%[1])                  | %[1] | |
+sim            | regorconst |
+                       "mov (.ignmask),%[1]"             | | |
+str $1==0      | rmorconst |
+                       "mov bp,%[1]"                     | | |
+str $1==1      | rmorconst |
+                       remove(ALL)
+                       "mov sp,%[1]"                     | | |
+str $1==2      | |
+                       remove(ALL)
+                       "call .strhp"                     | | |
+trp            | X_ACC |
+                       remove(ALL)
+                       "call .trp"                       | | |
+
+/********************************
+ * From source to register     *
+ ********************************/
+
+| rmorconst  | allocate(%[1],REG=%[1])         | %[a]  | |
+| reg_off |    "add %[1.reg],%[1.off]"
+               erase(%[1.reg]) setcc(%[1.reg]) 
+                                           | %[1.reg]  | |(2,3) + %[1]
+#ifdef DEEPER
+| halfindir |
+               allocate(%[1],REG)
+               move(%[1],%[a])
+               samecc                          | %[a]  | |(0,0)
+#else
+| halfindir |
+               allocate(%[1],ADDREG)
+               move(%[1],%[a])
+               samecc                          | %[a]  | |(0,0)
+#endif
+
+/********************************
+ * From source to token        *
+ ********************************/
+
+| ANYCON     |      | {ADDR_EXTERN,tostring(%[1.val])} | |
+
+/********************************
+ * From source1                *
+ ********************************/
+
+| rm1 |        allocate(%[1],REG1=%[1])        | %[a]  | |
+| rm1 |        allocate(%[1],GENREG)
+               move(%[1],%[a.1])
+               "xorb %[a.2],%[a.2]"            | %[a]  | |(2,3)
+| ACC1 |       allocate(%[1],ACC)
+               "xorb %[a.2],%[a.2]"            | %[a]  | |(2,3)
+/*
+| BLREG |      allocate(%[1],BXREG)
+               "xorb %[a.2],%[a.2]"            | %[a]  | |(2,3)
+*/
+
+
+
+/************************
+ * From STACK coercions *
+ ************************/
+
+| STACK |      allocate(REG)
+               "pop %[a]"
+               samecc                          | %[a]  | | (2,8)
+
+MOVES:
+(ACC,             EXTERN2,   "mov %[2],%[1]" samecc,      (3,16))
+(ACC1,            EXTERN1,   "movb %[2],%[1]" samecc,     (3,16))
+(ACC,             EXTERN1,   "movb %[2],%[1.1]" samecc,   (3,16))
+(EXTERN2,         ACC,       "mov %[2],%[1]" samecc,      (3,14))
+(EXTERN1,         ACC1,      "movb %[2],%[1]" samecc,     (3,14))
+(rm,              REG,       "mov %[2],%[1]" samecc,      (2,2) + %[1] )
+(anyreg,          dest,      "mov %[2],%[1]" samecc,      (2,3) + %[2] )
+(halfindir,       REG,       "lea %[2],%[1]" samecc,      (2,3) + %[1] )
+(rm1,             REG1,      "movb %[2],%[1]" samecc,     (2,2) + %[1] )
+(REG1,            rm1,       "movb %[2],%[1]" samecc,     (2,3) + %[2] )
+(GENREG,          rm1,       "movb %[2],%[1.1]" samecc,   (2,3) + %[2] )
+(ANYCON %[val]==0, REG,       "xor %[2],%[2]" setcc(%[2]), (2,3))
+(ANYCON %[val]==0, REG1,      "xorb %[2],%[2]" setcc(%[2]),(2,3))
+(const,           REG,       "mov %[2],%[1]" samecc,      (3,4))
+(const,           REG1,      "movb %[2],%[1]" samecc,     (2,4))
+(const,           dest,      "mov %[2],%[1]" samecc,      (4,4) + %[2] )
+(const,           rm1,       "movb %[2],%[1]" samecc,     (3,4) + %[2] )
+
+TESTS:
+(anyreg,       "or %[1],%[1]",         (2,3))
+(memory2,      "cmp %[1],0",           (3,11)+%[1])
+(REG1,         "orb %[1],%[1]",        (2,3))
+(memory1,      "cmpb %[1],0",          (3,11)+%[1])
+
+STACKS:
+(anyreg, ,     "push %[1]"
+               samecc                        ,  (1,10) )
+(memory2, ,    "push %[1]"
+               samecc                        ,  (2,10) + %[1] )
+(const, REG,   move(%[1],%[a])
+               "push %[a]"
+               samecc                        ,  (4,11) )
+(const, ,      ".data\n1: .word %[1]\n.text"
+               "push (1b)"
+               samecc                        ,  (6,24) )
+(rm1, GENREG,  move({ANYCON,0},%[a])
+               move(%[1],%[a.1])
+               "push %[a]"
+               samecc                        ,  (2,10) + %[1] )
+(rm1, ,        "push %[1]"
+               "push si"
+               "mov si,sp"
+               "movb 3(si),0"
+               "pop si"
+               samecc                        ,  (10,60) + %[1] )
+(reg_off, ,    "add %[1.reg],%[1.off]"
+               "push %[1.reg]"
+               erase(%[1.reg])
+               setcc(%[1.reg])               ,  ( 4,14) )
+(bpreg_off, ,  move(%[1],%[1.reg])
+               "push %[1.reg]"
+               samecc                        ,  ( 6,17) + %[1] )
+(ADDR_LOCAL %[ind]==0, ,
+               "push bp"
+               samecc                        ,  ( 1,10) )
+(halfindir, REG,move(%[1],%[a])
+               "push %[a]"
+               samecc                        ,  ( 6,17) + %[1] )
+(halfindir, ,  "push ax"
+               "push si"
+               "lea ax,%[1]"
+               "mov si,sp"
+               "xchg 2(si),ax"
+               "pop si"
+               samecc                        ,  (10,59) + %[1] )