/*
 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
 * See the copyright notice in the ACK home directory, in the file "Copyright".
 */

rscid = "$Header$"

/*
 * Back end tables for Intel 8086, 80286
 *
 * Author : Ed Keizer
 *
 * Adapted to ncg format by BMT Mosseveld, EM v Mulligen, M de Rooy, E tulp,
 * and R Vendelmans (practical work course compiler construction).
 *
 * New format table much corrected: Ceriel Jacobs
 * Added register variables: Ceriel Jacobs
 * Adapted to use floating point library: Ceriel Jacobs
 *
 * 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
 *
 */

SL = 4
SSL = "4"

EM_WSIZE = 2
EM_PSIZE = 2
EM_BSIZE = 4

SIZEFACTOR = 5/1

#define EXACT exact
#define REGVARS

/*****************************************************************/
PROPERTIES
/*****************************************************************/

REG1
ACC1
AREG
SHIFT_CREG
REG
GENREG
ACC
BREG
BXREG
ADDREG
CXREG
DXREG
IREG
#ifdef REGVARS
RADDREG
#endif

/*****************************************************************/
REGISTERS
/*****************************************************************/

al                                  : REG1 , ACC1 .
ah,bl,bh,ch,dl,dh                   : REG1 .
cl                                  : REG1 , SHIFT_CREG .
ax = al + ah                        : REG , GENREG , ACC .
bx = bl + bh                        : REG , GENREG , BXREG , ADDREG , AREG .
cx = cl + ch                        : REG , GENREG , CXREG , SHIFT_CREG.
dx = dl + dh                        : REG , GENREG , DXREG .
#ifndef REGVARS
si                                  : REG , IREG , AREG , ADDREG .
di                                  : REG , IREG , AREG , ADDREG .
#else
si				    : AREG , RADDREG , IREG regvar(reg_any) .
di				    : AREG , RADDREG , IREG regvar(reg_any) .
#endif
bp                                  : AREG .
sp				    : BREG .

/*****************************************************************/
TOKENS
/*****************************************************************/

ANYCON          = { INT val; }      2 cost(2,2) val .
CONSTR		= { ADDR off; }	    2 cost(2,2) off .
ADDR_EXTERN     = { ADDR off; }     2 cost(2,2) off .
EXTERN1         = { ADDR off; }     2 cost(2,12) "(" off ")" .
EXTERN2         = { ADDR off; }     2 cost(2,12) "(" off ")" .
ADDR_LOCAL      = { INT ind; }      2 cost(1,9) ind "(bp)" .
LOCAL          = { INT ind; INT size; } 2 cost(1,15) ind "(bp)" .
LOCAL1          = { INT ind; INT size; } 2 cost(1,15) ind "(bp)" .

Rreg_off         = { AREG reg; ADDR off;} 2 cost(1,9) off "(" reg ")" .
Rbpreg_off       = { AREG reg; INT ind;} 2 cost(1,11) ind "(bp)" "(" reg ")" .
Xreg_off         = { AREG reg; ADDR off;} 2 cost(1,9) off "(" reg ")" .

ind_reg2        = { AREG reg;} 2 cost(0,11) "(" reg ")" .
ind_regoff2     = { AREG reg; ADDR off;} 2 cost(1,15) off "(" reg ")" .
ind_bpregoff2   = { AREG reg; INT ind;} 2 cost(1,18) ind "(bp)" "(" reg ")" .

ind_reg1        = { AREG reg;} 2 cost(0,11) "(" reg ")" .
ind_regoff1     = { AREG reg; ADDR off;} 2 cost(1,15) off "(" reg ")" .
ind_bpregoff1   = { AREG reg; INT ind;} 2 cost(1,18) ind "(bp)" "(" reg ")" .
label           = { ADDR off;} 2 off .

/*****************************************************************/
SETS
/*****************************************************************/

/* Mode refering to a word in memory */
memory2 	= EXTERN2 + ind_reg2 + ind_regoff2 + ind_bpregoff2 +
                  LOCAL .


memory1 	= EXTERN1 + ind_reg1 + ind_regoff1 + ind_bpregoff1 +
                  LOCAL1 .

const		= ANYCON + ADDR_EXTERN + CONSTR .
register	= REG + AREG
#ifdef REGVARS
		  + IREG
#endif
			.
addreg		= ADDREG
#ifdef REGVARS
		  + RADDREG
#endif
			.
anyreg		= register + BREG .
rm		= anyreg + memory2 .
rmnoacc		= IREG + BXREG + CXREG + memory2 .
rmorconst	= const + rm .
regorconst	= const + anyreg .
#ifdef REGVARS
/* Needed because there is a shortage of ADDREG-registers.
   This is the main penalty for having register variables.
*/
regorconstnoaddr = const + IREG + ACC + CXREG + DXREG .
#else
regorconstnoaddr = regorconst .
#endif
dest		= register + memory2 .

rm1		= REG1 + memory1 .
rmorconst1	= const + rm1 .
regorconst12	= REG1 + GENREG + const .
dest1		= REG1 + memory1 .
rm12		= rm1 + memory2 .

/* 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		= LOCAL + LOCAL1 .
all_locals	= locals + lb_indexed .
indirects	= externals + reg_indexed .
referals	= indirects + locals .

/* Miscellaneous */
reg_off		= Xreg_off + Rreg_off .
bpreg_off	= Rbpreg_off .
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 .
 
/*****************************************************************/
INSTRUCTIONS
/*****************************************************************/

cost(1,3)
adc rm:rw:cc, regorconst:ro.
adc anyreg:rw:cc, rmorconst:ro.
#ifdef REGVARS
add LOCAL:rw:cc, rmorconst:ro.	/* only for register variables; UNSAFE !!! */
#endif
add anyreg:rw:cc, rmorconst:ro.
add rm:rw:cc, regorconst:ro.
#ifdef REGVARS
axx "syntax error" LOCAL:rw:cc, rmorconst:ro.	/* only for register variables; UNSAFE !!! */
#endif
axx "syntax error" anyreg:rw:cc, rmorconst:ro.
axx "syntax error" rm:rw:cc, regorconst:ro.
#ifdef REGVARS
and LOCAL:rw:cc, rmorconst:ro.	/* only for register variables; UNSAFE !!! */
#endif
and rm:rw:cc, regorconst:ro.
and anyreg:rw:cc, rmorconst:ro.
cbw kills ah cost(1,2).
cmp rm:ro, regorconst:ro kills :cc.
cmp anyreg:ro, rmorconst:ro kills :cc.
cmpb rm1:ro, REG1+const:ro kills :cc.
cmpb REG1:ro, rm1:ro kills :cc.
cwd kills dx cost(1,5).
dec rm:rw:cc cost(1,2).
div rm:ro kills:cc ax dx cost(1,150).
idiv rm:ro kills:cc ax dx cost(1,170).
inc rm:rw:cc cost(1,2).
ja label cost(1,4).
jae label cost(1,4).
jb label cost(1,4).
jbe label cost(1,4).
jcxz label cost(1,5).
je label cost(1,4).
jg label cost(1,4).
jge label cost(1,4).
jl label cost(1,4).
jle label cost(1,4).
jne label cost(1,4).
jmp label cost(1,7).
joehoe "call" label+rm cost(1,8).
jxx "syntax error" label.
lea anyreg:wo, halfindir:ro cost(1,2).
lea LOCAL:wo, halfindir:ro cost(1,2).	/* only for register variables, UNSAFE!!! */
loop label kills cx cost(1,5).
#ifdef REGVARS
mov LOCAL:wo, memory2:ro cost(1,2).	/* only for register variables, UNSAFE!!! */
#endif
mov a_word:wo, regorconst:ro cost(1,2).
mov anyreg:wo, rmorconst:ro cost(1,2).
movb rm1:wo, regorconst12:ro cost(1,2).
movb REG1:wo, rm1:ro cost(1,2).
mul rmorconst:ro kills :cc ax dx cost(1,124).
neg rmorconst:rw:cc.
nop .
not rmorconst:rw.
ORB "orb" REG1:ro, REG1:ro:cc.		/* use ORB for tests */
OR "or" anyreg:ro, anyreg:ro:cc.	/* Use OR for tests */
#ifdef REGVARS
or LOCAL:rw:cc, rmorconst:ro.	/* only for register variables; UNSAFE !!! */
#endif
or rm:rw:cc, regorconst:ro.
or anyreg:rw:cc, rmorconst:ro.
pop rmorconst+rm1:wo cost(1,8).
push rmorconst+rm1:ro cost(1,10).
rcl rm:rw:cc, ANYCON+SHIFT_CREG:ro.
rcr rm:rw:cc, ANYCON+SHIFT_CREG:ro.
ret cost(1,8).
rol rm:rw:cc, ANYCON+SHIFT_CREG:ro.
ror rm:rw:cc, ANYCON+SHIFT_CREG:ro.
sal rm:rw:cc, ANYCON+SHIFT_CREG:ro.
sar rm:rw:cc, ANYCON+SHIFT_CREG:ro.
sbb rm:rw:cc, regorconst:ro.
sbb anyreg:rw:cc, rmorconst:ro.
shl rm:rw:cc, ANYCON+SHIFT_CREG:ro.
shr rm:rw:cc, ANYCON+SHIFT_CREG:ro.
sxx rm:rw:cc, ANYCON+SHIFT_CREG:ro.
#ifdef REGVARS
sub LOCAL:rw:cc, rmorconst:ro.	/* only for register variables; UNSAFE !!! */
#endif
sub rm:rw:cc, regorconst:ro.
sub anyreg:rw:cc, rmorconst+halfindir:ro.
check "test" rm:ro, regorconst:ro kills :cc.
check "test" anyreg:ro, rmorconst:ro kills :cc.
testb "testb" rm12:ro, regorconst:ro kills :cc.
testb "testb" REG1:ro, rmorconst:ro kills :cc.
testb "testb" ACC1:ro, const:ro kills :cc.
uxx "syntax error"  rm:rw:cc cost(1,2).
xchg rm:rw, anyreg:rw.
xchg anyreg:rw, rm:rw.
xor rm:rw:cc, regorconst:ro.
xor anyreg:rw:cc, rmorconst:ro.
xorb rm1:rw:cc, regorconst12:ro.
xorb anyreg:rw:cc, rm1:ro.
killreg "! kill" anyreg:wo cost(0,0).

data ".sect .data".
word ".data2" const:ro.
text ".sect .text".


/*****************************************************************/
MOVES
/*****************************************************************/

#ifdef REGVARS
from memory2 to LOCAL		/* unsafe !!! */
gen mov %2,%1

from halfindir to LOCAL		/* unsafe !!! */
gen lea %2,%1
#endif

from rm to register
gen mov %2,%1

from anyreg to dest
gen mov %2,%1

from halfindir to register+AREG
gen lea %2,%1

from rm1 to REG1
gen movb %2,%1

from GENREG to rm1
gen movb %2,%1.1

from ANYCON %val==0 to register
gen xor %2,%2

from ANYCON %val==0 to REG1
gen xorb %2,%2

from const to dest
gen mov %2,%1

from const+REG1 to rm1
gen movb %2,%1


/*****************************************************************/
TESTS
/*****************************************************************/

to test anyreg
gen OR %1,%1

to test memory2
gen cmp %1, {ANYCON,0}

to test REG1
gen ORB %1,%1

to test memory1
gen cmpb %1, {ANYCON,0}


/*****************************************************************/
STACKINGRULES
/*****************************************************************/

from anyreg to STACK
  gen push %1

from memory2 to STACK
  gen push %1

from const to STACK
  uses REG
  gen move %1,%a
      push %a

from const to STACK
  gen data.
      1:
      word %1
      text.
      push {EXTERN2,"1b"}

from rm1 to STACK
  uses GENREG
  gen move {ANYCON,0},%a
      move %1,%a.1
      push %a

from rm1 to STACK
  gen push %1
      push bx
      mov bx,sp
      movb {ind_regoff1,bx,3},{ANYCON,0}
      pop bx

from Xreg_off to STACK
  gen add %1.reg,{CONSTR,%1.off}
      push %1.reg

from ADDR_LOCAL %ind==0 to STACK
  gen 
	push bp

from halfindir to STACK
  uses REG
  gen move %1,%a
      push %a

from halfindir to STACK
  gen push ax
      push bx
      lea ax,%1
      mov bx,sp
      xchg {ind_regoff2,bx,2},ax
      pop bx


/*****************************************************************/
COERCIONS
/*****************************************************************/

/***************************
 * From source to register *
 ***************************/

from rmorconst
  uses reusing %1,REG=%1		yields %a

from Xreg_off
  gen add %1.reg,{CONSTR,%1.off}	yields %1.reg

from halfindir
  uses reusing %1,ADDREG
  gen move %1,%a			yields %a

from halfindir
  uses reusing %1,REG
  gen move %1,%a			yields %a

/************************
 * From source to token *
 ************************/

from ANYCON				yields {ADDR_EXTERN,%1.val}

/****************
 * From source1 *
 ****************/

from rm1
  uses reusing %1,REG1=%1		yields %a

from rm1
  uses reusing %1,GENREG
  gen move %1,%a.1
      xorb %a.2,%a.2			yields %a

from ACC1
  uses reusing %1,ACC
  gen xorb %a.2,%a.2			yields %a

/************************
 * From STACK coercions *
 ************************/

from STACK
  uses REG
  gen pop %a				yields %a


/*****************************************************************/
PATTERNS
/*****************************************************************/

/******************************************************************
 *  Group 1 : Load Instructions                                   *
 ******************************************************************/

pat loc					yields {ANYCON,$1}

pat ldc loww($1)==0 && highw($1)==0
uses REG = {ANYCON, 0}			yields %a %a

pat ldc					yields {ANYCON,highw($1)}
				       	       {ANYCON,loww($1)}

pat lol					yields {LOCAL,$1,2}

pat stl lol $1==$2
#ifdef REGVARS
	&& inreg($1) <= 0
#endif
						leaving dup 2 stl $1

pat stl lol lof $1==$2
#ifdef REGVARS
	&& inreg($1) <= 0
#endif
with AREG				yields %1 %1
						leaving stl $1 lof $3

pat stl lol loi $1==$2
#ifdef REGVARS
	&& inreg($1) <= 0
#endif
with AREG				yields %1 %1
						leaving stl $1 loi $3

pat sdl ldl $1==$2				leaving dup 4 sdl $1

pat lol lol $1==$2
#ifdef REGVARS
	    && inreg($1) <= 0
#endif
						leaving lol $1 dup 2

#ifdef REGVARS
pat lol lol stl $1==$2 && inreg($1) <= 0 && inreg($3) > 0
kills regvar($3)
gen	move {LOCAL,$1,2}, {LOCAL,$3,2}
					yields {LOCAL,$3,2}
#endif

pat loe					yields {EXTERN2,$1}

pat ste loe $1==$2				leaving dup 2 ste $1

pat ste loe lof $1==$2
with AREG				yields %1 %1
						leaving ste $1 lof $3

pat ste loe loi $1==$2
with AREG				yields %1 %1
						leaving ste $1 loi $3

pat sde lde $1==$2				leaving dup 4 sde $1

pat loe loe $1==$2				leaving loe $1 dup 2

#ifdef REGVARS
pat loe loe stl $1==$2 && inreg($3) > 0
kills regvar($3)
gen	move {EXTERN2,$1}, {LOCAL,$3,2}
					yields {LOCAL,$3,2}
#endif

#ifdef REGVARS
pat lil inreg($1) > 0			yields {ind_reg2, regvar($1)}
#endif
pat lil	
  uses ADDREG={LOCAL,$1,2}	    	yields {ind_reg2,%a}

pat lil lil $1==$2				leaving lil $1 dup 2

pat lil lil stl $1==$2				leaving lil $1 stl $3 lol $3

pat sil lil $1==$2				leaving dup 2 sil $1

pat lof	
  with exact reg_off		yields {ind_regoff2,%1.reg,%1.off+$1}
  with exact bpreg_off		yields {ind_bpregoff2,%1.reg,%1.ind+$1}
  with exact ADDR_EXTERN	yields {EXTERN2,%1.off+$1}
  with exact ADDR_LOCAL		yields {LOCAL,%1.ind + $1,2}
  with addreg			yields {ind_regoff2,%1,$1}

pat lal					yields {ADDR_LOCAL,$1}

pat lae					yields {ADDR_EXTERN,$1}

pat lpb 					leaving adp SL

pat lxl $1==0				yields {ADDR_LOCAL,0}

pat lxl $1==1				yields {LOCAL,SL,2}

pat lxl $1==2				
  uses ADDREG={LOCAL,SL,2}		yields {ind_regoff2,%a,SSL}

pat lxl $1>2				
  uses ADDREG={LOCAL,SL,2},
       CXREG={ANYCON,$1-1}
  gen 1:
      mov %a,{ind_regoff2,%a,4}
      loop {label,1b}			yields %a

pat lxa $1==0				yields {ADDR_LOCAL,SL}

pat lxa $1==1 				
  uses ADDREG={LOCAL,SL,2}		yields {Xreg_off,%a,SSL}

pat lxa $1==2
  uses ADDREG={LOCAL,SL,2}
  gen move {ind_regoff2,%a,SSL},%a	yields {Xreg_off,%a,SSL}

pat lxa $1>2	
  uses ADDREG={LOCAL,SL,2},
       CXREG={ANYCON,$1-1}
  gen 1:
      mov %a,{ind_regoff2,%a,4}
      loop {label,1b}			yields {Xreg_off,%a,SSL}

pat dch						leaving loi 2

pat loi $1==2			
  with addreg			yields {ind_reg2,%1}
  with exact reg_off		yields {ind_regoff2,%1.reg,%1.off}
  with exact bpreg_off		yields {ind_bpregoff2,%1.reg,%1.ind}
  with exact ADDR_EXTERN	yields {EXTERN2,%1.off}
  with exact ADDR_LOCAL		yields {LOCAL,%1.ind,2}

pat loi $1==1
  with addreg			yields {ind_reg1,%1}
  with exact reg_off		yields {ind_regoff1,%1.reg,%1.off}
  with exact bpreg_off		yields {ind_bpregoff1,%1.reg,%1.ind}
  with exact ADDR_EXTERN	yields {EXTERN1,%1.off}
  with exact ADDR_LOCAL		yields {LOCAL1,%1.ind,1}

pat loi $1==4
  with addreg			yields {ind_regoff2,%1,2}
				       {ind_reg2,%1}
  with exact reg_off		yields {ind_regoff2,%1.reg,%1.off+2}
  				       {ind_regoff2,%1.reg,%1.off}
  with exact bpreg_off		yields {ind_bpregoff2,%1.reg,%1.ind+2}
				       {ind_bpregoff2,%1.reg,%1.ind}
  with exact ADDR_LOCAL         yields {LOCAL,%1.ind+2,2}
				       {LOCAL,%1.ind,2}
  with exact ADDR_EXTERN	yields {EXTERN2,%1.off + 2}
 				       {EXTERN2,%1.off}

pat loi $1>4
  with BXREG
  kills ALL
  gen mov cx,{ANYCON,$1}
      joehoe {label,".loi"}

pat los $1==2
  with CXREG BXREG
  kills ALL
  gen joehoe {label,".los"}

pat ldl					yields {LOCAL,$1+2,2}
					       {LOCAL,$1,2}

pat lde 				yields {EXTERN2,$1 + 2}
					       {EXTERN2,$1}

pat ldf	
  with exact reg_off			yields {ind_regoff2,%1.reg,
					        %1.off + 2 + $1}
 					       {ind_regoff2,%1.reg,
 						%1.off + $1}
  with addreg				yields {ind_regoff2,%1,$1+2}
                                               {ind_regoff2,%1,$1}
  with exact bpreg_off	yields {ind_bpregoff2,%1.reg,%1.ind+2+$1}
			       {ind_bpregoff2,%1.reg,%1.ind+$1}
  with exact ADDR_EXTERN	yields {EXTERN2,%1.off+2+$1}
				       {EXTERN2,%1.off+$1}
  with exact ADDR_LOCAL		yields {LOCAL,%1.ind + $1 + 2,2}
				       {LOCAL,%1.ind + $1,2}

pat lpi				yields {ADDR_EXTERN,$1}

/* this code sequence is generated by the C-compiler to tackle
   char parameters, on the 8086 it reduces to nil */

pat lol lal sti $1==$2 && $3<=2

/*******************************************************************
 *  Group 2 : Store Instructions                                   *
 *******************************************************************/

#ifdef REGVARS
pat stl inreg($1)==reg_any
  with rmorconst
  kills regvar($1)
  gen move %1, {LOCAL,$1,2}
  with halfindir
  kills regvar($1)
  gen move %1, {LOCAL,$1,2}
  with exact STACK
  kills regvar($1)
  gen pop {LOCAL, $1, 2}
#endif
pat stl
  with regorconst
  kills indexed,locals %ind+%size > $1 && %ind < $1+2
  gen move %1,{LOCAL,$1,2}
  with exact STACK
  kills indexed,locals %ind+%size > $1 && %ind < $1+2
  gen pop {LOCAL,$1,2}

pat ste
  with regorconst
  kills indirects
  gen move %1,{EXTERN2,$1}
  with exact STACK
  kills indirects
  gen pop {EXTERN2,$1}

#ifdef REGVARS
pat sil inreg($1)==reg_any
  with regorconst
  kills referals
  gen move %1,{ind_reg2,regvar($1)}
  with exact STACK
  kills referals
  gen pop {ind_reg2,regvar($1)}
#endif
pat sil
  with regorconstnoaddr
  kills referals
  uses ADDREG={LOCAL,$1,2}
  gen move %1,{ind_reg2,%a}
      killreg %a
  with exact STACK
  kills referals
  uses ADDREG={LOCAL,$1,2}
  gen pop {ind_reg2,%a}
      killreg %a

pat stf
  with addreg regorconst
  kills referals
  gen move %2,{ind_regoff2,%1,$1}
  with exact addreg STACK
  kills referals
  gen pop {ind_regoff2, %1,$1}
  with reg_off regorconst
  kills referals
  gen move %2,{ind_regoff2,%1.reg,%1.off+$1}
  with exact reg_off STACK
  kills referals
  gen pop {ind_regoff2,%1.reg,$1+%1.off}
  with exact bpreg_off STACK
  kills all_locals, indexed
  gen pop {ind_bpregoff2,%1.reg,$1+%1.ind}
  with ADDR_LOCAL regorconst
  kills indexed,locals %ind+%size > %1.ind+$1 && %ind < %1.ind+$1+2
  gen move %2,{LOCAL,%1.ind+$1,2}
  with exact ADDR_LOCAL STACK
  kills indexed,locals %ind+%size > %1.ind+$1 && %ind < %1.ind+$1+2
  gen pop {LOCAL,%1.ind+$1,2}
  with bpreg_off regorconst
  kills all_locals,indexed
  gen move %2,{ind_bpregoff2,%1.reg,%1.ind+$1}
  with ADDR_EXTERN regorconst
  kills indirects
  gen move %2,{EXTERN2,%1.off+$1}
  with exact ADDR_EXTERN STACK
  kills indirects
  gen pop {EXTERN2,%1.off+$1}

pat sti $1==2
  with addreg regorconst
  kills referals
  gen move %2,{ind_reg2,%1}
  with exact addreg STACK
  kills referals
  gen pop {ind_reg2,%1}
  with reg_off regorconst
  kills referals
  gen move %2,{ind_regoff2,%1.reg,%1.off}
  with exact reg_off STACK
  kills referals
  gen pop {ind_regoff2,%1.reg,%1.off}
  with bpreg_off regorconst
  kills all_locals,indexed
  gen move %2,{ind_bpregoff2,%1.reg,%1.ind}
  with exact bpreg_off STACK
  kills all_locals,indexed
  gen pop {ind_bpregoff2,%1.reg,%1.ind}
  with ADDR_EXTERN regorconst
  kills indirects
  gen move %2,{EXTERN2,%1.off}
  with exact ADDR_EXTERN STACK
  kills indirects
  gen pop {EXTERN2,%1.off}
  with ADDR_LOCAL regorconst
  kills indexed,locals %ind+%size > %1.ind && %ind < %1.ind+2
  gen move %2,{LOCAL,%1.ind,2}
  with exact ADDR_LOCAL STACK
  kills indexed,locals %ind+%size > %1.ind && %ind < %1.ind+2
  gen pop {LOCAL,%1.ind,2}

pat sti $1==1
  with addreg regorconst12
  kills referals
  gen move %2,{ind_reg1,%1}
  with reg_off regorconst12
  kills referals
  gen move %2,{ind_regoff1,%1.reg,%1.off}
  with bpreg_off regorconst12
  kills all_locals,indexed
  gen move %2,{ind_bpregoff1,%1.reg,%1.ind}
  with ADDR_EXTERN regorconst12
  kills indirects
  gen move %2,{EXTERN1,%1.off}
  with ADDR_LOCAL regorconst12
  kills indexed,locals %ind+%size > %1.ind && %ind <= %1.ind
  gen move %2,{LOCAL1,%1.ind,1}

pat sti $1==4				leaving sdf 0

pat sti $1>4
  with BXREG
  kills ALL
  gen mov cx,{ANYCON,$1}
      joehoe {label, ".sti"}

/* this sort of construction gives problems in the codegenerator
   because of the potential very large lookahead                 

  with addreg 
  kills ALL
  gen pop (%1)
      add %1,{ANYCON,2} 		yields %1	leaving sti $1-2

*/

pat sts $1==2
  with CXREG BXREG
  kills ALL
  gen joehoe {label,".sts"}

pat sdl
  with regorconst regorconst	yields %2 %1
					leaving stl $1 stl $1+2
  with exact STACK			leaving stl $1 stl $1+2

pat sde
  with regorconst regorconst	yields %2 %1
					leaving ste $1 ste $1+2
  with exact STACK			leaving ste $1 ste $1+2

pat sdf		
  with addreg regorconst regorconst
  kills referals
  gen move %2,{ind_regoff2,%1,$1}
      move %3,{ind_regoff2,%1,$1+2}
  with exact addreg STACK
  kills referals
  gen pop {ind_regoff2,%1,$1}
      pop {ind_regoff2,%1,$1+2}
  with exact halfindir STACK
  kills referals
  uses reusing %1,ADDREG=%1
  gen pop {ind_regoff2,%a,$1}
      pop {ind_regoff2,%a,$1+2}
  with exact memory2 STACK
  kills referals
  uses reusing %1,ADDREG=%1
  gen pop {ind_regoff2,%a,$1}
      pop {ind_regoff2,%a,$1+2}
  with reg_off regorconst regorconst
  kills referals
  gen move %2,{ind_regoff2,%1.reg,%1.off+$1}
      move %3,{ind_regoff2,%1.reg,%1.off+$1+2}
  with exact reg_off STACK
  kills referals
  gen pop {ind_regoff2,%1.reg,$1+%1.off}
      pop {ind_regoff2,%1.reg,$1+2+%1.off}
  with exact bpreg_off STACK
  kills all_locals,indexed
  gen pop {ind_bpregoff2, %1.reg,$1+%1.ind}
      pop {ind_bpregoff2, %1.reg,$1+2+%1.ind}
  with ADDR_LOCAL regorconst regorconst
  kills indexed,locals %ind+%size > %1.ind+$1 && %ind < %1.ind+$1+4
  gen	move %2,{LOCAL,%1.ind+$1,2}
	move %3,{LOCAL,%1.ind+$1+2,2}
  with exact ADDR_LOCAL STACK
  kills indexed,locals %ind+%size > %1.ind+$1 && %ind < %1.ind+$1+4
  gen	pop {LOCAL,%1.ind+$1,2}
	pop {LOCAL,%1.ind+$1+2,2}
  with ADDR_EXTERN regorconst regorconst
  kills indirects
  gen	move %2,{EXTERN2,%1.off+$1}
	move %3,{EXTERN2,%1.off+$1+2}
  with exact ADDR_EXTERN STACK
  kills indirects
  gen	pop {EXTERN2,%1.off+$1}
	pop {EXTERN2,%1.off+$1+2}
  with bpreg_off regorconst regorconst
  kills all_locals,indexed
  gen move %2,{ind_bpregoff2,%1.reg,%1.ind+$1}
      move %3,{ind_bpregoff2,%1.reg,%1.ind+$1+2}


/****************************************************************
 *  Group 3 : Integer Arithmetic.				*
 *								*
 *  Implemented (sometimes with the use of subroutines) :	*
 *  all 2 and 4 byte arithmetic. 				*
 ****************************************************************/

pat adi $1==2
#ifdef REGVARS
with exact ANYCON IREG
				yields {Rreg_off,%2,%1.val}
with exact IREG ANYCON
				yields {Rreg_off,%1,%2.val}
#endif
with REG rmorconst
  gen add %1,%2			yields %1
with rmorconst REG
  gen add %2,%1			yields %2
with EXACT rmorconst const
  uses reusing %1,REG=%1
  gen add %a,%2			yields %a

pat adi $1==4
with EXACT REG REG rmorconst rmorconst
  gen add %1,%3
      adc %2,%4			yields %2 %1
with rmorconst rmorconst REG REG
  gen add %3,%1
      adc %4,%2			yields %4 %3

pat adi !defined($1)
with CXREG ACC
  kills ALL
  gen joehoe {label,".adi"}	yields ax

pat sbi $1==2

with rmorconst REG
  gen sub %2,%1			yields %2
with EXACT REG rmorconst
  gen sub %1,%2
      neg %1			yields %1

pat sbi $1==4
with rmorconst rmorconst REG REG
  gen sub %3,%1
      sbb %4,%2			yields %4 %3

pat sbi !defined($1)
with CXREG ACC
  kills ALL
  gen joehoe {label,".sbi"}	yields ax

pat mli $1==2
with ACC rm
  uses reusing %2,DXREG
  gen mul %2			yields %1
			/* mul and imul have same low order result
			   but mul is faster
			*/

with rmnoacc rmorconst
  uses reusing %2,DXREG,ACC=%2
  gen mul %1			yields %b

pat mli $1==4
with ACC DXREG
  kills ALL
  gen joehoe {label,".mli4"}	yields dx ax

/* 
pat mli !defined($1)
with ACC
  kills ALL
  gen joehoe {label,".mli"}
*/

pat dvi $1==2
with rmnoacc rmorconst
  uses reusing %2,DXREG,ACC=%2
  gen cwd.
      idiv %1			yields ax

pat dvi $1==4
kills ALL
  gen joehoe {label,".dvi4"}	yields dx ax

/*
pat dvi !defined($1)
with ACC
  kills ALL
  gen joehoe {label,".dvi"}
*/

pat rmi $1==2
with rmnoacc rmorconst
  uses reusing %2, ACC=%2, DXREG
  gen cwd.
      idiv %1			yields dx

pat rmi $1==4
kills ALL
  gen joehoe {label,".rmi4"}	yields dx ax

/*
pat rmi !defined($1)
with ACC
  kills ALL
  gen joehoe {label,".rmi"}
*/

pat ngi $1==2
with REG
  gen neg %1			yields %1

pat ngi $1==4
with REG REG
  gen neg %2
      neg %1
      sbb %2,{ANYCON,0}		yields %2 %1

/*
pat ngi !defined($1)
with ACC
  kills ALL
  gen joehoe {label,".ngi"}
*/

pat loc sli $1==1 && $2==2
with REG
  gen sal %1,{ANYCON,1}		yields %1

pat loc sli $1==1 && $2==4
with REG REG
  gen sal %1,{ANYCON,1}
      rcl %2,{ANYCON,1}		yields %2 %1

pat loc sli $1==2 && $2==4
with REG REG
  gen sal %1,{ANYCON,1}
      rcl %2,{ANYCON,1}
      sal %1,{ANYCON,1}
      rcl %2,{ANYCON,1}		yields %2 %1

pat loc sli $1==3 && $2==4
with REG REG
  gen sal %1,{ANYCON,1}
      rcl %2,{ANYCON,1}
      sal %1,{ANYCON,1}
      rcl %2,{ANYCON,1}
      sal %1,{ANYCON,1}
      rcl %2,{ANYCON,1}		yields %2 %1

pat loc sli $1==16 && $2==4
with rmorconst rmorconst	yields %1 {ANYCON,0}

pat sli $1==2
with SHIFT_CREG REG
  gen sal %2,cl			yields %2

pat sli $1==4
with CXREG REG REG
  gen jcxz {label,1f}
      2:
      sal %2,{ANYCON,1}
      rcl %3,{ANYCON,1}
      loop {label,2b}
      1:
				yields %3 %2

/*
pat sli !defined($1)
with ACC
  kills ALL
  gen joehoe {label,".sli"}
*/

pat loc sri $1==1 && $2==2
with REG
  gen sar %1,{ANYCON,1}		yields %1

pat loc sri $1==1 && $2==4
with REG REG
  gen sar %2,{ANYCON,1}
      rcr %1,{ANYCON,1}		yields %2 %1

pat loc sri $1==2 && $2==4
with REG REG
  gen sar %2,{ANYCON,1}
      rcr %1,{ANYCON,1}
      sar %2,{ANYCON,1}
      rcr %1,{ANYCON,1}		yields %2 %1

pat loc sri $1==3 && $2==4
with REG REG
  gen sar %2,{ANYCON,1}
      rcr %1,{ANYCON,1}
      sar %2,{ANYCON,1}
      rcr %1,{ANYCON,1}
      sar %2,{ANYCON,1}
      rcr %1,{ANYCON,1}		yields %2 %1

pat sri $1==2
with SHIFT_CREG REG
  gen sar %2,cl			yields %2

pat sri $1==4
with CXREG REG REG
  gen jcxz {label,1f}
      2:
      sar %3,{ANYCON,1}
      rcr %2,{ANYCON,1}
      loop {label,2b}
      1:
				yields %3 %2

/*
pat sri !defined($1)
with ACC
  kills ALL
  gen joehoe {label,".sri"}
*/

/*******************************************************************
 *  Group 4: Unsigned Arithmetic                                   *
 *******************************************************************/

pat adu					leaving adi $1
pat loc lol adu stl $1==1 && $3==2 && $2==$4	leaving inl $2
pat loc loe adu ste $1==1 && $3==2 && $2==$4	leaving ine $2
pat loc lol adu $1==1 && $3==2		leaving lol $2 inc
pat loc loe adu $1==1 && $3==2		leaving loe $2 inc
pat loc lil adu $1==1 && $3==2		leaving lil $2 inc
pat loc lol adu stl $1==0-1 && $3==2 && $2==$4	leaving del $2
pat loc loe adu ste $1==0-1 && $3==2 && $2==$4	leaving dee $2
pat loc lol adu $1==0-1 && $3==2		leaving lol $2 dec
pat loc loe adu $1==0-1 && $3==2		leaving loe $2 dec
pat loc lil adu $1==0-1 && $3==2		leaving lil $2 dec
pat sbu					leaving sbi $1
pat lol loc sbu stl $1==$4 && $2==1 && $3==2	leaving del $1
pat loe loc sbu ste $1==$4 && $2==1 && $3==2	leaving dee $1
pat lol loc sbu $2==1 && $3==2		leaving lol $1 dec
pat loe loc sbu $2==1 && $3==2		leaving loe $1 dec
pat lil loc sbu $2==1 && $3==2		leaving lil $1 dec
pat lol loc sbu stl $1==$4 && $2==0-1 && $3==2	leaving inl $1
pat loe loc sbu ste $1==$4 && $2==0-1 && $3==2	leaving ine $1
pat lol loc sbu $2==0-1 && $3==2		leaving lol $1 inc
pat loe loc sbu $2==0-1 && $3==2		leaving loe $1 inc
pat lil loc sbu $2==0-1 && $3==2		leaving lil $1 inc
pat mlu					leaving mli $1

pat loe loc loe adu ste $1==$3 && $1==$5 && $4==2
uses REG = {EXTERN2, $1}
				yields %a leaving loc $2 loe $3 adu 2 ste $3

pat lol loc lol adu stl $1==$3 && $1==$5 && $4==2
uses REG = {LOCAL, $1, 2}
				yields %a leaving loc $2 lol $3 adu 2 stl $3

pat loe loc loe adi ste $1==$3 && $1==$5 && $4==2
uses REG = {EXTERN2, $1}
				yields %a leaving loc $2 loe $3 adi 2 ste $3

pat lol loc lol adi stl $1==$3 && $1==$5 && $4==2
uses REG = {LOCAL, $1, 2}
				yields %a leaving loc $2 lol $3 adi 2 stl $3

pat dvu $1==2
with rmnoacc rmorconst
uses reusing %2, ACC=%2,  DXREG={ANYCON,0}
gen div %1			yields ax

pat dvu $1==4
kills ALL
gen joehoe {label,".dvu4"}	yields dx ax

/*
pat dvu !defined($1)
with ACC STACK
kills ALL
gen joehoe {label,".dvu"}
*/

pat rmu $1==2
with rmnoacc rmorconst
uses reusing %2, ACC=%2, DXREG={ANYCON,0}
gen div %1			yields dx

pat rmu $1==4
kills ALL
gen joehoe {label,".rmu4"}	yields dx ax

/*
pat rmu !defined($1)
with ACC STACK
kills ALL
gen joehoe {label,".rmu"}
*/

pat slu					leaving sli $1
pat loc slu				leaving loc $1 sli $2

pat loc sru $1==1 && $2==2
with REG
gen shr %1,{ANYCON, 1}			yields %1

pat loc sru $1==16 && $2==4
with rmorconst rmorconst		yields {ANYCON,0} %2

pat sru $1==2
with SHIFT_CREG REG
gen shr %2,cl			yields %2

pat sru $1==4
with CXREG REG REG
gen jcxz {label,1f}
    2:
    shr %3,{ANYCON, 1}
    rcr %2,{ANYCON, 1}
    loop {label,2b}
    1:				yields %3 %2

/*
pat sru !defined($1)
with ACC STACK
kills ALL
gen joehoe {label,".sru"}
*/

/*******************************************************************
 *  Group 5: Floating Point Instructions                           *
 *******************************************************************/

pat adf $1==4		leaving cal ".adf4" asp 4
pat adf $1==8		leaving cal ".adf8" asp 8
pat sbf $1==4		leaving cal ".sbf4" asp 4
pat sbf $1==8		leaving cal ".sbf8" asp 8
pat mlf $1==4		leaving cal ".mlf4" asp 4
pat mlf $1==8		leaving cal ".mlf8" asp 8
pat dvf $1==4		leaving cal ".dvf4" asp 4
pat dvf $1==8		leaving cal ".dvf8" asp 8
pat ngf $1==4		leaving cal ".ngf4"
pat ngf $1==8		leaving cal ".ngf8"
pat fif $1==4		leaving lor 1 cal ".fif4" asp 2
pat fif $1==8		leaving lor 1 cal ".fif8" asp 2
pat fef $1==4		leaving lor 1 adp 0-2 cal ".fef4"
pat fef $1==8		leaving lor 1 adp 0-2 cal ".fef8"

/******************************************************************
 *  Group 6: Pointer Arithmetic                                   *
 ******************************************************************/

pat adp $1==1
with exact Xreg_off	yields {Xreg_off,%1.reg,%1.off+$1}
with exact Rreg_off	yields {Rreg_off,%1.reg,%1.off+$1}
with exact ADDR_EXTERN	yields {ADDR_EXTERN,%1.off+$1}
with exact ADDR_LOCAL	yields {ADDR_LOCAL,%1.ind+$1}
with exact Rbpreg_off	yields {Rbpreg_off,%1.reg,%1.ind+$1}
with REG
  gen inc %1		yields %1
with ADDREG
  gen killreg %1
			yields {Xreg_off, %1, $1}
with exact RADDREG	yields {Rreg_off, %1, $1}

pat adp $1==0-1
with exact Xreg_off	yields {Xreg_off,%1.reg,%1.off+$1}
with exact Rreg_off	yields {Rreg_off,%1.reg,%1.off+$1}
with exact ADDR_EXTERN  yields {ADDR_EXTERN,%1.off+$1}
with exact ADDR_LOCAL   yields {ADDR_LOCAL,%1.ind+$1}
with exact Rbpreg_off	yields {Rbpreg_off,%1.reg,%1.ind+$1}
with REG
  gen dec %1		yields %1
with ADDREG
  gen killreg %1
			yields {Xreg_off, %1, $1}
with exact RADDREG	yields {Rreg_off, %1, $1}

pat adp
with exact Xreg_off	yields {Xreg_off,%1.reg,%1.off+$1}
with exact Rreg_off	yields {Rreg_off,%1.reg,%1.off+$1}
with exact ADDR_EXTERN	yields {ADDR_EXTERN,%1.off+$1}
with exact ADDR_LOCAL	yields {ADDR_LOCAL,%1.ind+$1}
with exact Rbpreg_off	yields {Rbpreg_off,%1.reg,%1.ind+$1}
with ADDREG
  gen killreg %1
			yields {Xreg_off,%1,$1}
with exact RADDREG	yields {Rreg_off, %1, $1}
with REG
  gen add %1,{ANYCON,$1}	yields %1

pat ads stl $1==2			leaving adi 2 stl $2
pat ads ste $1==2			leaving adi 2 ste $2
pat ads sil $1==2			leaving adi 2 sil $2
pat ads lol stf $1==2			leaving adi 2 lol $2 stf $3
pat ads loe stf $1==2			leaving adi 2 loe $2 stf $3

pat ads $1==2
with exact ANYCON Rreg_off
			yields {Rreg_off,%2.reg,%2.off+%1.val}
with exact ANYCON Xreg_off
			yields {Xreg_off,%2.reg,%2.off+%1.val}
with exact ADDR_EXTERN Rreg_off
			yields {Rreg_off,%2.reg,%2.off+%1.off}
with exact ADDR_EXTERN Xreg_off
			yields {Xreg_off,%2.reg,%2.off+%1.off}
with rmorconst Xreg_off
  gen add %2.reg,%1	yields %2
with exact ANYCON Rbpreg_off
			yields {Rbpreg_off,%2.reg,%2.ind+%1.val}
with Xreg_off rmorconst
  gen add %1.reg,%2	yields %1
with exact Xreg_off ANYCON
			yields {Xreg_off,%1.reg,%1.off+%2.val}
with exact Rreg_off ANYCON
			yields {Rreg_off,%1.reg,%1.off+%2.val}
with exact Xreg_off ADDR_EXTERN
			yields {Xreg_off,%1.reg,%1.off+%2.off}
with exact Rreg_off ADDR_EXTERN
			yields {Rreg_off,%1.reg,%1.off+%2.off}
with exact Xreg_off reg_off
  gen add %1.reg,%2.reg
			yields {Xreg_off,%1.reg,%1.off+%2.off}
with exact IREG ADDR_LOCAL
			yields {Rbpreg_off, %1, %2.ind}
with exact IREG ADDR_EXTERN
			yields {Rreg_off, %1, %2.off}
with exact ADDR_EXTERN IREG
			yields {Rreg_off,%2,%1.off}
with exact ADDR_LOCAL IREG
			yields {Rbpreg_off,%2,%1.ind}

with exact rmorconst ADDR_EXTERN
  uses reusing %1,ADDREG=%1
			yields {Xreg_off,%a,%2.off}
with exact ADDR_EXTERN rmorconst
  uses reusing %2,ADDREG=%2
			yields {Xreg_off,%a,%1.off}
with rmorconst ADDREG
  gen add %2,%1		yields %2
with ADDREG rmorconst
  gen add %1,%2		yields %1

pat sbs $1==2
with exact ANYCON Xreg_off
			yields {Xreg_off,%2.reg,%2.off+"-"+%1.val}
with exact ANYCON Rreg_off
			yields {Rreg_off,%2.reg,%2.off+"-"+%1.val}
with exact ANYCON ADDR_LOCAL
			yields {ADDR_LOCAL,%2.ind-%1.val}
with rm Xreg_off
  gen sub %2.reg,%1	yields {Xreg_off,%2.reg,%2.off}

/* Should not occur
with exact reg_off ANYCON
			yields {reg_off,%1.reg,%1.off-%2.val}
with ANYCON ADDR_EXTERN
			yields {ADDR_EXTERN,%2.off+%1.val}
with exact ANYCON ADDR_LOCAL
			yields {ADDR_LOCAL,%1.val+%2.ind}
*/

with rm REG
  gen sub %2,%1		yields %2
with const ACC
  gen sub %2,%1		yields %2

/*******************************************************************
 *  Group 7 : Increment/Decrement Zero                             *
 *******************************************************************/

pat inc
with REG
gen inc %1			yields %1

#ifdef REGVARS
pat inl inreg($1)==reg_any
  kills regvar($1)
  gen inc {LOCAL,$1,2}
#endif

pat inl 
kills indexed,locals %ind+%size > $1 && %ind < $1+2
gen inc {LOCAL, $1, 2}

pat ine
kills indirects
gen inc {EXTERN2, $1}

pat dec
with REG
gen dec %1			yields %1

#ifdef REGVARS
pat del inreg($1)==reg_any
  kills regvar($1)
  gen dec {LOCAL,$1,2}
#endif

pat del 
kills indexed,locals %ind+%size > $1 && %ind < $1+2
gen dec {LOCAL, $1, 2}

pat dee
kills indirects
gen dec {EXTERN2, $1}

pat zrl				yields {ANYCON, 0}	leaving stl $1

pat zre				yields {ANYCON, 0}	leaving ste $1

pat zrf			leaving zer $1

pat zer $1==2			yields {ANYCON, 0}	
pat zer $1==4			yields {ANYCON, 0} {ANYCON, 0}	
pat zer $1==6			yields {ANYCON, 0} {ANYCON, 0} 
				       {ANYCON, 0}	
pat zer $1==8			yields {ANYCON, 0} {ANYCON, 0} 
				       {ANYCON, 0} {ANYCON, 0}	

pat zer defined($1)
with STACK
gen move {ANYCON, $1/2}, cx
    move {ANYCON, 0}, bx
    1:
    push bx
    loop {label,1b}

pat zer !defined($1)
with CXREG STACK
gen move {ANYCON, 0}, bx
    sar cx,{ANYCON, 1}
    1:
    push bx
    loop {label,1b}

#ifdef REGVARS
proc lolrxxxstl example lol adi stl
with rmorconst
  kills regvar($1)
  gen axx* {LOCAL, $1, 2}, %1

proc lilrxxxsil example lil adi sil
with regorconst
kills referals
gen axx* {ind_reg2, regvar($1)}, %1

pat lol adi stl $1==$3 && $2==2 && inreg($1)==reg_any	call lolrxxxstl("add")
pat lol adu stl $1==$3 && $2==2 && inreg($1)==reg_any	call lolrxxxstl("add")
pat lol ads stl $1==$3 && $2==2 && inreg($1)==reg_any	call lolrxxxstl("add")
pat lol and stl $1==$3 && $2==2 && inreg($1)==reg_any	call lolrxxxstl("and")
pat lol ior stl $1==$3 && $2==2 && inreg($1)==reg_any	call lolrxxxstl("or")
pat lol xor stl $1==$3 && $2==2 && inreg($1)==reg_any	call lolrxxxstl("xor")

pat lil adi sil $1==$3 && $2==2 && inreg($1)==reg_any	call lilrxxxsil("add")
pat lil adu sil $1==$3 && $2==2 && inreg($1)==reg_any	call lilrxxxsil("add")
pat lil ads sil $1==$3 && $2==2 && inreg($1)==reg_any	call lilrxxxsil("add")
pat lil and sil $1==$3 && $2==2 && inreg($1)==reg_any	call lilrxxxsil("and")
pat lil ior sil $1==$3 && $2==2 && inreg($1)==reg_any	call lilrxxxsil("or")
pat lil xor sil $1==$3 && $2==2 && inreg($1)==reg_any	call lilrxxxsil("xor")
#endif

proc lolxxxstl example lol adi stl
with regorconst
kills indexed,locals %ind+%size > $1 && %ind < $1+2
gen axx* {LOCAL, $1, 2}, %1

pat lol adi stl $1==$3 && $2==2		call lolxxxstl("add")
pat lol adu stl $1==$3 && $2==2		call lolxxxstl("add")
pat lol ads stl $1==$3 && $2==2		call lolxxxstl("add")
pat lol and stl $1==$3 && $2==2		call lolxxxstl("and")
pat lol ior stl $1==$3 && $2==2		call lolxxxstl("or")
pat lol xor stl $1==$3 && $2==2		call lolxxxstl("xor")

proc lilxxxsil example lil adi sil
with regorconst
kills referals
uses ADDREG={LOCAL, $1, 2}
gen axx* {ind_reg2, %a}, %1
    killreg %a

pat lil adi sil $1==$3 && $2==2		call lilxxxsil("add")
pat lil adu sil $1==$3 && $2==2		call lilxxxsil("add")
pat lil ads sil $1==$3 && $2==2		call lilxxxsil("add")
pat lil and sil $1==$3 && $2==2		call lilxxxsil("and")
pat lil ior sil $1==$3 && $2==2		call lilxxxsil("or")
pat lil xor sil $1==$3 && $2==2		call lilxxxsil("xor")

#ifdef REGVARS
proc lilruxxsil example lil ngi sil
kills referals
gen uxx* {ind_reg2, regvar($1)}

pat lil ngi sil $1==$3 && $2==2 && inreg($1)==reg_any	call lilruxxsil("neg")
pat lil com sil $1==$3 && $2==2 && inreg($1)==reg_any	call lilruxxsil("not")
pat lil dec sil $1==$3 && inreg($1)==reg_any		call lilruxxsil("dec")
pat lil inc sil $1==$3 && inreg($1)==reg_any		call lilruxxsil("inc")
#endif

proc liluxxsil example lil ngi sil
kills referals
uses ADDREG={LOCAL, $1, 2}
gen uxx* {ind_reg2, %a}
    killreg %a

pat lil ngi sil $1==$3 && $2==2		call liluxxsil("neg")
pat lil com sil $1==$3 && $2==2		call liluxxsil("not")
pat lil dec sil $1==$3 			call liluxxsil("dec")
pat lil inc sil $1==$3 			call liluxxsil("inc")

proc loexxxste example loe adi ste
with regorconst
kills indirects
gen axx* {EXTERN2, $1}, %1

pat loe adi ste $1==$3 && $2==2		call loexxxste("add")
pat loe adu ste $1==$3 && $2==2		call loexxxste("add")
pat loe ads ste $1==$3 && $2==2		call loexxxste("add")
pat loe and ste $1==$3 && $2==2		call loexxxste("and")
pat loe ior ste $1==$3 && $2==2		call loexxxste("or")
pat loe xor ste $1==$3 && $2==2		call loexxxste("xor")

proc ldlxxxsdl example ldl adi sdl
with regorconst regorconst
  kills indexed,locals %ind+%size > $1 && %ind < $1+4
  gen axx[1] {LOCAL,$1,2},%1
      axx[2] {LOCAL,$1+2,2},%2

pat ldl adi sdl $1==$3 && $2==4		call ldlxxxsdl("add", "adc")
pat ldl adu sdl $1==$3 && $2==4		call ldlxxxsdl("add", "adc")
pat ldl and sdl $1==$3 && $2==4		call ldlxxxsdl("and", "and")
pat ldl ior sdl $1==$3 && $2==4		call ldlxxxsdl("or", "or")
pat ldl xor sdl $1==$3 && $2==4		call ldlxxxsdl("xor", "xor")

proc ldlcxxsdl example ldl ldc sbi sdl
  kills indexed,locals %ind+%size > $1 && %ind < $1+4
  gen axx[1] {LOCAL,$1,2},{ANYCON,loww($2)}
      axx[2] {LOCAL,$1+2,2},{ANYCON,highw($2)}

pat ldl ldc sbi sdl $1==$4 && $3==4	call ldlcxxsdl("sub", "sbb")
pat ldl ldc sbu sdl $1==$4 && $3==4	call ldlcxxsdl("sub", "sbb")

proc ldexxxsde example lde adi sde
with regorconst regorconst
  kills indirects
  gen axx[1] {EXTERN2,$1},%1
      axx[2] {EXTERN2,$1+2},%2

pat lde adi sde $1==$3 && $2==4		call ldexxxsde("add", "adc")
pat lde adu sde $1==$3 && $2==4		call ldexxxsde("add", "adc")
pat lde and sde $1==$3 && $2==4		call ldexxxsde("and", "and")
pat lde ior sde $1==$3 && $2==4		call ldexxxsde("or", "or")
pat lde xor sde $1==$3 && $2==4		call ldexxxsde("xor", "xor")

#ifdef REGVARS
proc lofrxxxsof example lol lof adi lol stf
with regorconst
kills referals
gen axx* {ind_regoff2, regvar($1), $2}, %1

pat lol lof adi lol stf $1==$4 && $2==$5 && $3==2 && inreg($1)==reg_any
					call lofrxxxsof("add")
pat lol lof adu lol stf $1==$4 && $2==$5 && $3==2 && inreg($1)==reg_any
					call lofrxxxsof("add")
pat lol lof ads lol stf $1==$4 && $2==$5 && $3==2 && inreg($1)==reg_any
					call lofrxxxsof("add")
pat lol lof and lol stf $1==$4 && $2==$5 && $3==2 && inreg($1)==reg_any
					call lofrxxxsof("and")
pat lol lof ior lol stf $1==$4 && $2==$5 && $3==2 && inreg($1)==reg_any
					call lofrxxxsof("or")
pat lol lof xor lol stf $1==$4 && $2==$5 && $3==2 && inreg($1)==reg_any
					call lofrxxxsof("xor")

proc ldfrxxxsdf example lol ldf adi lol sdf
with regorconst regorconst
kills referals
gen axx[1] {ind_regoff2, regvar($1), $2}, %1
    axx[2] {ind_regoff2, regvar($1), $2+2}, %2

pat lol ldf adi lol sdf $1==$4 && $2==$5 && $3==4 && inreg($1)==reg_any
					call ldfrxxxsdf("add", "adc")
pat lol ldf adu lol sdf $1==$4 && $2==$5 && $3==4 && inreg($1)==reg_any
					call ldfrxxxsdf("add", "adc")
pat lol ldf and lol sdf $1==$4 && $2==$5 && $3==4 && inreg($1)==reg_any
					call ldfrxxxsdf("and", "and")
pat lol ldf ior lol sdf $1==$4 && $2==$5 && $3==4 && inreg($1)==reg_any
					call ldfrxxxsdf("or", "or")
pat lol ldf xor lol sdf $1==$4 && $2==$5 && $3==4 && inreg($1)==reg_any
					call ldfrxxxsdf("xor", "xor")

proc ldirxxxsdi example lol loi adi lol sti
with regorconst regorconst
kills referals
gen axx[1] {ind_reg2, regvar($1)}, %1
    axx[2] {ind_regoff2, regvar($1), 2}, %2

pat lol loi adi lol sti $1==$4 && $2==4 && $5==4 && $3==4 && inreg($1)==reg_any
					call ldirxxxsdi("add", "adc")
pat lol loi adu lol sti $1==$4 && $2==4 && $5==4 && $3==4 && inreg($1)==reg_any
					call ldirxxxsdi("add", "adc")
pat lol loi and lol sti $1==$4 && $2==4 && $5==4 && $3==4 && inreg($1)==reg_any
					call ldirxxxsdi("and", "and")
pat lol loi ior lol sti $1==$4 && $2==4 && $5==4 && $3==4 && inreg($1)==reg_any
					call ldirxxxsdi("or", "or")
pat lol loi xor lol sti $1==$4 && $2==4 && $5==4 && $3==4 && inreg($1)==reg_any
					call ldirxxxsdi("xor", "xor")

proc lofruxxsof example lol lof inc lol stf
kills referals
gen uxx* {ind_regoff2, regvar($1), $2}

pat lol lof inc lol stf $1==$4 && $2==$5 && inreg($1)==reg_any
					call lofruxxsof("inc")
pat lol lof dec lol stf $1==$4 && $2==$5 && inreg($1)==reg_any
					call lofruxxsof("dec")
pat lol lof ngi lol stf $1==$4 && $2==$5 && $3==2 && inreg($1)==reg_any
					call lofruxxsof("neg")
pat lol lof com lol stf $1==$4 && $2==$5 && $3==2 && inreg($1)==reg_any
					call lofruxxsof("not")
#endif

proc lofuxxsof example lol lof inc lol stf
kills referals
uses ADDREG={LOCAL,$1,2}
gen uxx* {ind_regoff2, %a, $2}
    killreg %a

pat lol lof ngi lol stf $1==$4 && $2==$5 && $3==2	call lofuxxsof("neg")
pat lol lof com lol stf $1==$4 && $2==$5 && $3==2	call lofuxxsof("not")
pat lol lof dec lol stf $1==$4 && $2==$5 		call lofuxxsof("dec")
pat lol lof inc lol stf $1==$4 && $2==$5 		call lofuxxsof("inc")

proc lofxxxsof example lol lof adi lol stf
with regorconstnoaddr
kills referals
uses ADDREG={LOCAL,$1,2}
gen axx* {ind_regoff2, %a, $2}, %1
    killreg %a

pat lol lof adi lol stf $1==$4 && $2==$5 && $3==2	call lofxxxsof("add")
pat lol lof adu lol stf $1==$4 && $2==$5 && $3==2	call lofxxxsof("add")
pat lol lof ads lol stf $1==$4 && $2==$5 && $3==2	call lofxxxsof("add")
pat lol lof and lol stf $1==$4 && $2==$5 && $3==2	call lofxxxsof("and")
pat lol lof ior lol stf $1==$4 && $2==$5 && $3==2	call lofxxxsof("or")
pat lol lof xor lol stf $1==$4 && $2==$5 && $3==2	call lofxxxsof("xor")

proc ldfxxxsdf example lol ldf adi lol sdf
with regorconstnoaddr regorconstnoaddr
kills referals
uses ADDREG={LOCAL,$1,2}
gen axx[1] {ind_regoff2, %a, $2}, %1
    axx[2] {ind_regoff2, %a, $2+2}, %2
    killreg %a

pat lol ldf adi lol sdf $1==$4 && $2==$5 && $3==4	call ldfxxxsdf("add", "adc")
pat lol ldf adu lol sdf $1==$4 && $2==$5 && $3==4	call ldfxxxsdf("add", "adc")
pat lol ldf and lol sdf $1==$4 && $2==$5 && $3==4	call ldfxxxsdf("and", "and")
pat lol ldf ior lol sdf $1==$4 && $2==$5 && $3==4	call ldfxxxsdf("or", "or")
pat lol ldf xor lol sdf $1==$4 && $2==$5 && $3==4	call ldfxxxsdf("xor", "xor")

proc ldixxxsdi example lol loi adi lol sti
with regorconstnoaddr regorconstnoaddr
kills referals
uses ADDREG={LOCAL,$1,2}
gen axx[1] {ind_reg2, %a}, %1
    axx[2] {ind_regoff2, %a, 2}, %2
    killreg %a

pat lol loi adi lol sti $1==$4 && $2==4 && $5==4 && $3==4
					call ldixxxsdi("add", "adc")
pat lol loi adu lol sti $1==$4 && $2==4 && $5==4 && $3==4
					call ldixxxsdi("add", "adc")
pat lol loi and lol sti $1==$4 && $2==4 && $5==4 && $3==4
					call ldixxxsdi("and", "and")
pat lol loi ior lol sti $1==$4 && $2==4 && $5==4 && $3==4
					call ldixxxsdi("or", "or")
pat lol loi xor lol sti $1==$4 && $2==4 && $5==4 && $3==4
					call ldixxxsdi("xor", "xor")

proc lefuxxsef example loe lof inc loe stf
kills referals
uses ADDREG={EXTERN2,$1}
gen uxx* {ind_regoff2, %a, $2}
    killreg %a

pat loe lof ngi loe stf $1==$4 && $2==$5 && $3==2	call lefuxxsef("neg")
pat loe lof com loe stf $1==$4 && $2==$5 && $3==2	call lefuxxsef("not")
pat loe lof dec loe stf $1==$4 && $2==$5 		call lefuxxsef("dec")
pat loe lof inc loe stf $1==$4 && $2==$5 		call lefuxxsef("inc")

proc lefxxxsef example loe lof adi loe stf
with regorconstnoaddr
kills referals
uses ADDREG={EXTERN2,$1}
gen axx* {ind_regoff2, %a, $2}, %1
    killreg %a

pat loe lof adi loe stf $1==$4 && $2==$5 && $3==2	call lefxxxsef("add")
pat loe lof adu loe stf $1==$4 && $2==$5 && $3==2	call lefxxxsef("add")
pat loe lof ads loe stf $1==$4 && $2==$5 && $3==2	call lefxxxsef("add")
pat loe lof and loe stf $1==$4 && $2==$5 && $3==2	call lefxxxsef("and")
pat loe lof ior loe stf $1==$4 && $2==$5 && $3==2	call lefxxxsef("or")
pat loe lof xor loe stf $1==$4 && $2==$5 && $3==2	call lefxxxsef("xor")

proc leiuxxsei example loe loi inc loe sti
kills referals
uses ADDREG={EXTERN2,$1}
gen uxx* {ind_reg2, %a}
    killreg %a

pat loe loi ngi loe sti $1==$4 && $2==2 && $5==2 && $3==2
							call leiuxxsei("neg")
pat loe loi com loe sti $1==$4 && $2==2 && $5==2 && $3==2
							call leiuxxsei("not")
pat loe loi dec loe sti $1==$4 && $2==2 && $5==2	call leiuxxsei("dec")
pat loe loi inc loe sti $1==$4 && $2==2 && $5==2	call leiuxxsei("inc")

proc leixxxsei example loe loi adi loe sti
with regorconstnoaddr
kills referals
uses ADDREG={EXTERN2,$1}
gen axx* {ind_reg2, %a}, %1
    killreg %a

pat loe loi adi loe sti $1==$4 && $2==$5 && $2==2 && $3==2	call leixxxsei("add")
pat loe loi adu loe sti $1==$4 && $2==$5 && $2==2 && $3==2	call leixxxsei("add")
pat loe loi ads loe sti $1==$4 && $2==$5 && $2==2 && $3==2	call leixxxsei("add")
pat loe loi and loe sti $1==$4 && $2==$5 && $2==2 && $3==2	call leixxxsei("and")
pat loe loi ior loe sti $1==$4 && $2==$5 && $2==2 && $3==2	call leixxxsei("or")
pat loe loi xor loe sti $1==$4 && $2==$5 && $2==2 && $3==2	call leixxxsei("xor")

#ifdef REGVARS
proc lolcrxxstl example lol loc sbi stl
  kills regvar($1)
  gen axx* {LOCAL,$1,2},{ANYCON,$2}

pat lol loc sbi stl $1==$4 && $3==2 && inreg($1)==reg_any
						call lolcrxxstl("sub")
pat lol loc sbu stl $1==$4 && $3==2 && inreg($1)==reg_any
						call lolcrxxstl("sub")
pat lol loc sli stl $1==$4 && $3==2 && $2==1 && inreg($1)==reg_any
						call lolcrxxstl("sal")
pat lol loc slu stl $1==$4 && $3==2 && $2==1 && inreg($1)==reg_any
						call lolcrxxstl("sal")
pat lol loc sri stl $1==$4 && $3==2 && $2==1 && inreg($1)==reg_any
						call lolcrxxstl("sar")
pat lol loc sru stl $1==$4 && $3==2 && $2==1 && inreg($1)==reg_any
						call lolcrxxstl("shr")

proc lolr2shstl example lol loc sli stl
  kills regvar($1)
  gen axx* {LOCAL,$1,2},{ANYCON,1}
      axx* {LOCAL,$1,2},{ANYCON,1}

pat lol loc sli stl $1==$4 && $3==2 && $2==2 && inreg($1)==reg_any
						call lolr2shstl("sal")
pat lol loc slu stl $1==$4 && $3==2 && $2==2 && inreg($1)==reg_any
						call lolr2shstl("sal")
pat lol loc sri stl $1==$4 && $3==2 && $2==2 && inreg($1)==reg_any
						call lolr2shstl("sar")
pat lol loc sru stl $1==$4 && $3==2 && $2==2 && inreg($1)==reg_any
						call lolr2shstl("shr")

proc lolrcshstl example lol loc sli stl
  kills regvar($1)
  uses CXREG = {ANYCON,$2}
  gen sxx* {LOCAL,$1,2},cl

pat lol loc sli stl $1==$4 && $3==2 && inreg($1)==reg_any
						call lolrcshstl("sal")
pat lol loc slu stl $1==$4 && $3==2 && inreg($1)==reg_any
						call lolrcshstl("sal")
pat lol loc sri stl $1==$4 && $3==2 && inreg($1)==reg_any
						call lolrcshstl("sar")
pat lol loc sru stl $1==$4 && $3==2 && inreg($1)==reg_any
						call lolrcshstl("shr")

#endif

proc lolcxxstl example lol loc sbi stl
  kills indexed,locals %ind+%size > $1 && %ind < $1+2
  gen axx* {LOCAL,$1,2},{ANYCON,$2}

pat lol loc sbi stl $1==$4 && $3==2		call lolcxxstl("sub")
pat lol loc sbu stl $1==$4 && $3==2		call lolcxxstl("sub")
pat lol loc sli stl $1==$4 && $3==2 && $2==1	call lolcxxstl("sal")
pat lol loc slu stl $1==$4 && $3==2 && $2==1	call lolcxxstl("sal")
pat lol loc sri stl $1==$4 && $3==2 && $2==1	call lolcxxstl("sar")
pat lol loc sru stl $1==$4 && $3==2 && $2==1	call lolcxxstl("shr")

proc lolcshstl example lol loc sli stl
  kills indexed,locals %ind+%size > $1 && %ind < $1+2
  uses CXREG = {ANYCON,$2}
  gen sxx* {LOCAL,$1,2},cl

pat lol loc sli stl $1==$4 && $3==2	call lolcshstl("sal")
pat lol loc slu stl $1==$4 && $3==2	call lolcshstl("sal")
pat lol loc sri stl $1==$4 && $3==2	call lolcshstl("sar")
pat lol loc sru stl $1==$4 && $3==2	call lolcshstl("shr")


proc loecxxste example loe loc sbi ste
  kills indirects
  gen axx* {EXTERN2,$1},{ANYCON,$2}

pat loe loc sbi ste $1==$4 && $3==2		call loecxxste("sub")
pat loe loc sbu ste $1==$4 && $3==2		call loecxxste("sub")
pat loe loc adu ste $1==$4 && $3==2		call loecxxste("add")
pat loe loc adi ste $1==$4 && $3==2		call loecxxste("add")
pat loe loc sli ste $1==$4 && $3==2 && $2==1	call loecxxste("sal")
pat loe loc slu ste $1==$4 && $3==2 && $2==1	call loecxxste("sal")
pat loe loc sri ste $1==$4 && $3==2 && $2==1	call loecxxste("sar")
pat loe loc sru ste $1==$4 && $3==2 && $2==1	call loecxxste("shr")

proc loecshste example loe loc sli ste
  kills indirects
  uses CXREG = {ANYCON,$2}
  gen sxx* {EXTERN2,$1},cl

pat loe loc sli ste $1==$4 && $3==2	call loecshste("sal")
pat loe loc slu ste $1==$4 && $3==2	call loecshste("sal")
pat loe loc sri ste $1==$4 && $3==2	call loecshste("sar")
pat loe loc sru ste $1==$4 && $3==2	call loecshste("shr")

#ifdef REGVARS
pat lol ngi stl $1==$3 && $2==2 && inreg($1)==reg_any
kills regvar($1)
gen neg {LOCAL, $1, 2}
#endif

pat lol ngi stl $1==$3 && $2==2
kills indexed,locals %ind+%size > $1 && %ind < $1+2
gen neg {LOCAL, $1, 2}

pat ldl ngi sdl $1==$3 && $2==4
kills indexed,locals %ind+%size > $1 && %ind < $1+4
gen neg {LOCAL, $1+2, 2}
    neg {LOCAL, $1, 2}
    sbb {LOCAL, $1+2, 2}, {ANYCON, 0}
 
pat lol lol adp stl loi stl $1==$2 && $2==$4 && $5<=2
					leaving lol $1 loi $5 stl $6 lol $2 adp $3 stl $4

#ifdef REGVARS
pat lol lol adp stl loi $1==$2 && $2==$4 && $5==1 && inreg($1) > 0
uses REG1 = {ind_reg1, regvar($1)}
				yields %a
					leaving lol $2 adp $3 stl $4

pat lol lol adp stl loi $1==$2 && $2==$4 && $5==2 && inreg($1) > 0
uses REG = {ind_reg2, regvar($1)}
				yields %a
					leaving lol $2 adp $3 stl $4
pat adp stl inreg($2) > 0		leaving stl $2 lol $2 adp $1 stl $2
#endif

pat lol lol adp stl $1==$2 && $2==$4
uses ADDREG={LOCAL,$1,2}	yields %a
					leaving lol $2 adp $3 stl $2

pat lol inl $1==$2
uses REG={LOCAL,$1,2}		yields %a
					leaving inl $1

pat lol del $1==$2
uses REG={LOCAL,$1,2}		yields %a
					leaving del $1

pat lol adp stl $1==$3 && $2==1		leaving inl $1
pat lol adp stl $1==$3 && $2==0-1	leaving del $1
pat lol adp stl $1==$3			leaving loc $2 lol $1 adi 2 stl $3

#ifdef REGVARS
pat lol com stl $1==$3 && $2==2 && inreg($1)==reg_any
kills regvar($1)
gen not {LOCAL,$1,2}
#endif

pat lol com stl $1==$3 && $2==2
kills indexed,locals %ind+%size > $1 && %ind < $1+2
gen not {LOCAL, $1, 2}

#ifdef REGVARS
pat lil lil adp sil $1==$2 && $1==$4 && inreg($1)==reg_any
uses ADDREG={ind_reg2, regvar($1)}
				yields %a
					leaving lil $1 adp $3 sil $4

pat lil lil inc sil $1==$2 && $1==$4 && inreg($1)==reg_any
uses REG={ind_reg2, regvar($1)}
				yields %a
					leaving lil $1 inc sil $4

pat lil lil dec sil $1==$2 && $1==$4 && inreg($1)==reg_any
uses REG={ind_reg2, regvar($1)}
				yields %a
					leaving lil $1 dec sil $4
#endif

pat lil adp sil $1==$3 && $2==1		leaving lil $1 inc sil $1

pat lil adp sil $1==$3 && $2==0-1	leaving lil $1 dec sil $1

pat lil adp sil $1==$3	 		leaving loc $2 lil $1 adi 2 sil $3

pat lol lof adp lol stf $1==$4 && $2==$5 && $3==1
	leaving lol $1 lof $2 inc lol $4 stf $5
pat lol lof adp lol stf $1==$4 && $2==$5 && $3==(0-1)
	leaving lol $1 lof $2 dec lol $4 stf $5
pat lol lof adp lol stf $1==$4 && $2==$5	
	leaving loc $3 lol $1 lof $2 adi 2 lol $4 stf $5

#ifdef REGVARS
pat lol lof lol lof adp lol stf 
	$1==$3 && $1==$6 && $2==$4 && $2==$7 && inreg($1)==reg_any
uses ADDREG={ind_regoff2, regvar($1), $2}
				yields %a
					leaving lol $1 lof $2 adp $5 lol $6 stf $7

pat lol lof lol lof inc lol stf
	$1==$3 && $1==$6 && $2==$4 && $2==$7 && inreg($1)==reg_any
uses REG={ind_regoff2, regvar($1), $2}
				yields %a
					leaving lol $1 lof $2 inc lol $6 stf $7

pat lol lof lol lof dec lol stf
	$1==$3 && $1==$6 && $2==$4 && $2==$7 && inreg($1)==reg_any
uses REG={ind_regoff2, regvar($1), $2}
				yields %a
					leaving lol $1 lof $2 dec lol $6 stf $7

pat lol lof dup adp lol stf 
	$1==$5 && $2==$6 && $3==2 && inreg($1)==reg_any
uses ADDREG={ind_regoff2, regvar($1), $2}
				yields %a
					leaving lol $1 lof $2 adp $4 lol $1 stf $2

pat lol lof dup inc lol stf 
	$1==$5 && $2==$6 && $3==2 && inreg($1)==reg_any
uses REG={ind_regoff2, regvar($1), $2}
				yields %a
					leaving lol $1 lof $2 inc lol $1 stf $2

pat lol lof dup dec lol stf 
	$1==$5 && $2==$6 && $3==2 && inreg($1)==reg_any
uses REG={ind_regoff2, regvar($1), $2}
				yields %a
					leaving lol $1 lof $2 dec lol $1 stf $2

#endif

pat lol lof dup adp lol stf
	$1==$5 && $2==$6 && $3==2 && $4==1
kills referals
uses ADDREG={LOCAL,$1,2}, REG
gen move {ind_regoff2, %a, $2},%b
    inc {ind_regoff2, %a, $2}
				yields %b

pat loe lof dup adp loe stf
	$1==$5 && $2==$6 && $3==2 && $4==1
kills referals
uses ADDREG={EXTERN2,$1}, REG
gen move {ind_regoff2, %a, $2},%b
    inc {ind_regoff2, %a, $2}
				yields %b

pat loe loi dup adp loe sti
	$1==$5 && $2==$6 && $3==2 && $2==2 && $4==1
kills referals
uses ADDREG={EXTERN2,$1}, REG
gen move {ind_reg2, %a},%b
    inc {ind_reg2, %a}
				yields %b

pat lol lof dup adp lol stf
	$1==$5 && $2==$6 && $3==2 && $4==(0-1)
kills referals
uses ADDREG={LOCAL,$1,2}, REG
gen move {ind_regoff2, %a, $2},%b
    dec {ind_regoff2, %a, $2}
				yields %b

pat loe lof dup adp loe stf
	$1==$5 && $2==$6 && $3==2 && $4==(0-1)
kills referals
uses ADDREG={EXTERN2,$1}, REG
gen move {ind_regoff2, %a, $2},%b
    dec {ind_regoff2, %a, $2}
				yields %b

pat loe loi dup adp loe sti
	$1==$5 && $2==$6 && $3==2 && $2==2 && $4==(0-1)
kills referals
uses ADDREG={EXTERN2,$1}, REG
gen move {ind_reg2, %a},%b
    dec {ind_reg2, %a}
				yields %b

pat lol lof dup adp lol stf
	$1==$5 && $2==$6 && $3==2
kills referals
uses ADDREG={LOCAL,$1,2}, REG
gen move {ind_regoff2, %a, $2},%b
    add {ind_regoff2, %a, $2}, {ANYCON, $4}
				yields %b

pat loe lof dup adp loe stf
	$1==$5 && $2==$6 && $3==2
kills referals
uses ADDREG={EXTERN2,$1}, REG
gen move {ind_regoff2, %a, $2},%b
    add {ind_regoff2, %a, $2}, {ANYCON, $4}
				yields %b

pat loe loi dup adp loe sti
	$1==$5 && $2==$6 && $3==2 && $2==2
kills referals
uses ADDREG={EXTERN2,$1}, REG
gen move {ind_reg2, %a},%b
    add {ind_reg2, %a}, {ANYCON, $4}
				yields %b

pat loe ngi ste $1==$3 && $2==2
kills indirects
gen neg {EXTERN2, $1}

pat lde ngi sde $1==$3 && $2==4
kills indirects
gen neg {EXTERN2, $1+2}
    neg {EXTERN2, $1}
    sbb {EXTERN2, $1+2}, {ANYCON, 0}

pat loe loe adp ste $1==$2 && $1==$4
uses ADDREG={EXTERN2,$1}	yields %a
					leaving loe $1 adp $3 ste $1

pat loe ine $1==$2
uses REG={EXTERN2,$1}	yields %a	leaving ine $1

pat loe dee $1==$2
uses REG={EXTERN2,$1}	yields %a	leaving dee $1

pat loe adp ste $1==$3 && $2==1		leaving ine $1

pat loe adp ste $1==$3 && $2==0-1	leaving dee $1

pat loe adp ste $1==$3			leaving loc $2 loe $1 adi 2 ste $3

pat loe com ste $1==$3 && $2==2
kills indirects
gen not {EXTERN2, $1}

pat loe lof adp loe stf $1==$4 && $2==$5 && $3==1
	leaving loe $1 lof $2 inc loe $1 stf $2
pat loe lof adp loe stf $1==$4 && $2==$5 && $3==0-1
	leaving loe $1 lof $2 dec loe $1 stf $2
pat loe lof adp loe stf $1==$4 && $2==$5
	leaving loc $3 loe $1 lof $2 adi 2 loe $1 stf $2

pat loe loi adp loe sti $1==$4 && $2==$5 && $3==1 && $2==2
	leaving loe $1 loi $2 inc loe $1 sti $2
pat loe loi adp loe sti $1==$4 && $2==$5 && $3==0-1 && $2==2
	leaving loe $1 loi $2 dec loe $1 sti $2
pat loe loi adp loe sti $1==$4 && $2==$5 && $2==2
	leaving loc $3 loe $1 loi $2 adi 2 loe $1 sti $2

/*******************************************************************
 *  Group 8: Convert Instructions                                  *
 *******************************************************************/

pat cii
with CXREG DXREG ACC
kills ALL
gen joehoe {label,".cii"}		yields %3

pat ciu					leaving cuu
pat cui					leaving cuu

pat cuu
with CXREG DXREG ACC
kills ALL
gen joehoe {label,".cuu"}		yields %3

pat loc loc cii zeq $1==1 && $2==2
with GENREG
gen test %1.1
    je {label, $4}

pat loc loc cii zne $1==1 && $2==2
with GENREG
gen test %1.1
    jne {label, $4}

pat loc loc cii loc and zeq $4<256 && $4>=0 && $5==2 && $1==1 && $2==2
		leaving loc $4 and $5 zeq $6
pat loc loc cii loc and zne $4<256 && $4>=0 && $5==2 && $1==1 && $2==2
		leaving loc $4 and $5 zne $6

pat loc loc cii $1==1 && $2==2
with ACC
gen cbw.			yields ax
with exact rmorconst1 ACC
uses REG
gen move %2,%a
    move %1,%2.1
    cbw.			yields %a ax
with exact rmorconst1
uses reusing %1, ACC1=%1
gen cbw.			yields ax

pat loc loc cii $1==1 && $2==4
with ACC
uses DXREG
gen cbw.	
    cwd.			yields dx ax
with exact rmorconst1
uses reusing %1, ACC1=%1, DXREG
gen cbw.	
    cwd.			yields dx ax

pat loc loc cii $1==2 && $2==4
with ACC
uses DXREG
gen  cwd.			yields dx ax

pat loc loc cii $1==4 && $2==2
with a_word a_word		yields %1

pat loc loc ciu				leaving loc $1 loc $2 cuu
pat loc loc cui				leaving loc $1 loc $2 cuu

pat loc loc cuu $1==$2

pat loc loc cuu $1==2 && $2==4
with a_word			yields {ANYCON,0} %1

pat loc loc cuu $1==4 && $2==2
with a_word a_word		yields %1

pat loc loc cif $1==2 && $2==4		leaving loc $1 cal ".cif4"
pat loc loc cif $1==4 && $2==4		leaving loc $1 cal ".cif4" asp 2

pat loc loc cif $1==2 && $2==8
with REG
kills ALL
  gen push %1
      push %1
      push %1				leaving loc $1 cal ".cif8"

pat loc loc cif $1==4 && $2==8
with REG REG
kills ALL
  gen push %1
      push %2
      push %1				leaving loc $1 cal ".cif8"

pat loc loc cuf $1==2 && $2==4		leaving loc $1 cal ".cuf4"
pat loc loc cuf $1==4 && $2==4		leaving loc $1 cal ".cuf4" asp 2

pat loc loc cuf $1==2 && $2==8
with REG
kills ALL
  gen push %1
      push %1
      push %1				leaving loc $1 cal ".cuf8"

pat loc loc cuf $1==4 && $2==8
with REG REG
kills ALL
  gen push %1
      push %2
      push %1				leaving loc $1 cal ".cuf8"

pat loc loc cfi $1==4 && $2==2	leaving loc $1 loc $2 cal ".cfi" asp 8 lfr 2
pat loc loc cfi $2==4		leaving loc $1 loc $2 cal ".cfi" asp $1
pat loc loc cfi $1==8 && $2==2	leaving loc $1 loc $2 cal ".cfi" asp 12 lfr 2
pat loc loc cfu $1==4 && $2==2	leaving loc $1 loc $2 cal ".cfu" asp 8 lfr 2
pat loc loc cfu $2==4		leaving loc $1 loc $2 cal ".cfu" asp $1
pat loc loc cfu $1==8 && $2==2	leaving loc $1 loc $2 cal ".cfu" asp 12 lfr 2
pat loc loc cff $1==8 && $2==4	leaving cal ".cff4" asp 4
pat loc loc cff $1==4 && $2==8
with REG REG
kills ALL
uses REG={ANYCON,0}
  gen push %a
      push %a
      push %2
      push %1			leaving cal ".cff8"

/********************************************************************
 *  Group 9 : Logical Instructions                                  *
 ********************************************************************/

pat and $1==2
with REG rmorconst
  gen and %1,%2				yields %1
with rmorconst REG
  gen and %2,%1				yields %2

pat loc and $1==65535 && $2==2

pat loc and $1==255 && $2==2
with GENREG				yields %1.1

pat loc and $1==0 && $2==2		leaving asp 2 loc 0

pat and $1==4
with EXACT REG REG rmorconst rmorconst
  gen and %1,%3
      and %2,%4				yields %2 %1
with rmorconst rmorconst REG REG
  gen and %3,%1
      and %4,%2				yields %4 %3

pat ldc and highw($1)==(0-1) && $2==4	leaving loc loww($1) and 2

pat ldc and loww($1)==0 && $2==4	leaving asp 2 loc highw($1) and 2 loc 0

pat ldc and loww($1)==65535 && $2==4
with rmorconst REG
  gen and %2,{ANYCON, highw($1)}	yields %2 %1

pat ldc and highw($1)==0 && $2==4
with REG rmorconst
  gen and %1,{ANYCON, loww($1)}		yields {ANYCON,0} %1

pat and defined($1)
kills ALL
  gen mov cx,{ANYCON,$1}
      joehoe {label, ".and"}

pat and !defined($1)
with CXREG
kills ALL
  gen joehoe {label, ".and"}

pat ior $1==2
with REG rmorconst
  gen or %1,%2				yields %1
with rmorconst REG
  gen or %2,%1				yields %2

pat loc ior $1==0 && $2==2

pat loc ior $1==65535 && $2==2		leaving asp 2 loc $1

pat ior $1==4
with EXACT REG REG rmorconst rmorconst
  gen or %1,%3
      or %2,%4				yields %2 %1
with rmorconst rmorconst REG REG
  gen or %3,%1
      or %4,%2				yields %4 %3

pat ldc ior highw($1)==(0-1) && $2==4
with REG rmorconst
  gen or %1,{ANYCON, loww($1)}		yields {ANYCON,0-1} %1

pat ldc ior highw($1)==0 && $2==4	leaving loc loww($1) ior 2

pat ldc ior loww($1)==65535 && $2==4	leaving asp 2 loc highw($1) ior 2 loc 0-1

pat ldc ior loww($1)==0 && $2==4
with rmorconst REG
  gen or %2,{ANYCON, highw($1)}		yields %2 %1

pat ior defined($1)
kills ALL
  gen mov cx,{ANYCON,$1}
      joehoe {label, ".ior"}

pat ior !defined($1)
with CXREG
kills ALL
  gen joehoe {label, ".ior"}

pat xor $1==2
with REG rmorconst
  gen xor %1,%2				yields %1
with rmorconst REG
  gen xor %2,%1				yields %2

pat xor $1==4
with EXACT REG REG rmorconst rmorconst
  gen xor %1,%3
      xor %2,%4				yields %2 %1
with rmorconst rmorconst REG REG
  gen xor %3,%1
      xor %4,%2				yields %4 %3

pat xor defined($1)
kills ALL
  gen mov cx,{ANYCON,$1}
      joehoe {label, ".xor"}

pat xor !defined($1)
with CXREG
kills ALL
  gen joehoe {label, ".xor"}

pat com $1==2
with REG
  gen not %1				yields %1

pat com $1==4
with REG REG
  gen not %2
      not %1				yields %2 %1

pat com defined($1)
kills ALL
  gen mov cx,{ANYCON,$1}
      joehoe {label, ".com"}

pat com !defined($1)
with CXREG
kills ALL
  gen joehoe {label, ".com"}

pat loc rol $1==1 && $2==2
with REG
  gen rol %1,{ANYCON,1}			yields %1

pat rol $1==2
with SHIFT_CREG REG
  gen rol %2,cl				yields %2

pat rol $1==4
with CXREG REG REG
  gen jcxz {label, 1f}
      2: sal %2,{ANYCON,1}
      rcl %3,{ANYCON,1}
      adc %2,{ANYCON,0}
      loop {label, 2b}
      1:

pat loc ror $1==1 && $2==2
with REG
  gen ror %1,{ANYCON,1}			yields %1

pat ror $1==2
with SHIFT_CREG REG
  gen ror %2,cl				yields %2

pat ror $1==4
with CXREG REG REG
  gen jcxz {label, 1f}
      neg cx
      add cx,{ANYCON,32}
      2: sal %2,{ANYCON,1}
      rcl %3,{ANYCON,1}
      adc %2,{ANYCON,0}
      loop {label, 2b}
      1:

/*******************************************************************
 *  Group 10 : Set Instructions                                    *
 *******************************************************************/

pat inn $1==2
with SHIFT_CREG REG
gen shr %2,cl
    and %2,{ANYCON, 1}			yields %2

pat loc inn $1==1 && $2==2
with REG
gen shr %1,{ANYCON, 1}
    and %1,{ANYCON, 1}			yields %1

pat loc inn $1==0 && $2==2
with REG
gen and %1,{ANYCON, 1}			yields %1

pat inn defined($1)
with ACC 
kills ALL
gen mov cx,{ANYCON, $1}
    joehoe {label,".inn"}		yields ax

pat inn !defined($1)
with CXREG ACC
kills ALL
gen joehoe {label,".inn"}		yields ax

pat loc inn zeq $2==2
with rm STACK
gen check %1,{ANYCON,1<<$1}
    je {label,$3}

pat loc inn zne $2==2
with rm STACK
gen check %1,{ANYCON,1<<$1}
    jne {label,$3}

pat set $1==2
with SHIFT_CREG
uses REG={ANYCON, 1}
gen shl %a,cl			yields %a

pat set defined($1)
with ACC
kills ALL
gen mov cx,{ANYCON, $1}
    joehoe {label,".set"}

pat set !defined($1)
with CXREG ACC
kills ALL
gen joehoe {label,".set"}

/********************************************************************
 *  Group 11 : Array Instructions                                   *
 ********************************************************************/

pat lae aar $2==2 && rom($1,3)==1 && rom($1,1)==0
						leaving ads 2

pat lae aar $2==2 && rom($1,3)==1 && rom($1,1)!=0
					leaving adp 0-rom($1,1) ads 2

pat lae aar $2==2 && rom($1,3)==2 && rom($1,1)==0
  with ADDREG
  gen sal %1,{ANYCON,1}			yields %1	leaving ads 2

pat lae aar $2==2 && rom($1,3)==2 && rom($1,1)!=0
  with ADDREG
  gen sal %1,{ANYCON,1}     yields %1   leaving adp 0-2*rom($1,1) ads 2

pat lae aar $2==2 && rom($1,3)==4 && rom($1,1)==0
  with ADDREG
  gen sal %1,{ANYCON,1}
      sal %1,{ANYCON,1}			yields %1	leaving ads 2

pat lae aar $2==2 && rom($1,3)==4 && rom($1,1)!=0
  with ADDREG
  gen sal %1,{ANYCON,1}
      sal %1,{ANYCON,1}  yields %1	leaving adp 0-4*rom($1,1) ads 2

pat lae aar $2==2 && rom($1,1)==0
  with ACC
  uses DXREG,REG={ANYCON,rom($1,3)}
  gen mul %b			yields %1	leaving ads 2

pat lae aar $2==2 && defined(rom($1,1))
  with ACC
  uses DXREG,REG={ANYCON,rom($1,3)}
  gen mul %b 		yields %1
   				leaving adp 0-rom($1,1)*rom($1,3) ads 2
 
pat loc sli ads sti $1==1 && $2==2 && $3==2
with exact rmorconst ADDR_EXTERN
  uses reusing %1,ADDREG=%1
  gen sal %a,{ANYCON,1}		yields {Xreg_off,%a,%2.off}
						leaving sti $4
with ADDREG rmorconst
  gen sal %1,{ANYCON,1}
  add %1,%2			yields %1	leaving sti $4
with REG ADDREG
  gen sal %1,{ANYCON,1}
      add %2,%1			yields %2	leaving sti $4

pat loc sli ads $1==1 && $2==2 && $3==2
with exact rmorconst ADDR_EXTERN
  uses reusing %1,ADDREG=%1
  gen sal %a,{ANYCON,1}		yields {Xreg_off,%a,%2.off}
with ADDREG rmorconst
  gen sal %1,{ANYCON,1}
  add %1,%2			yields %1
with REG ADDREG
  gen sal %1,{ANYCON,1}
      add %2,%1			yields %2
with REG rmorconst
  gen sal %1,{ANYCON,1}
  add %1,%2			yields %1

pat loc sli ads sti $1==2 && $2==2 && $3==2
with exact rmorconst ADDR_EXTERN
  uses reusing %1,ADDREG=%1
  gen sal %a,{ANYCON,1}
      sal %a,{ANYCON,1}		yields {Xreg_off,%a,%2.off}
						leaving sti $4
with ADDREG rmorconst
  gen sal %1,{ANYCON,1}
      sal %1,{ANYCON,1}
      add %1,%2			yields %1	leaving sti $4
with REG ADDREG
  gen sal %1,{ANYCON,1}
      sal %1,{ANYCON,1}
      add %2,%1			yields %2	leaving sti $4

pat loc sli ads $1==2 && $2==2 && $3==2
with exact rmorconst ADDR_EXTERN
  uses reusing %1,ADDREG=%1
  gen sal %a,{ANYCON,1}
      sal %a,{ANYCON,1}		yields {Xreg_off,%a,%2.off}
with ADDREG rmorconst
  gen sal %1,{ANYCON,1}
      sal %1,{ANYCON,1}
      add %1,%2			yields %1
with REG ADDREG
  gen sal %1,{ANYCON,1}
      sal %1,{ANYCON,1}
      add %2,%1			yields %2
with REG rmorconst
  gen sal %1,{ANYCON,1}
      sal %1,{ANYCON,1}
      add %1,%2			yields %1

pat loc sli ads sti $2==2 && $3==2
with exact rmorconst ADDR_EXTERN
uses reusing %1,ADDREG=%1,CXREG={ANYCON,$1}
  gen sal %a,cl			yields {Xreg_off,%a,%2.off}
						leaving sti $4
with ADDREG rmorconst
uses CXREG={ANYCON,$1}
  gen sal %1,cl
      add %1,%2			yields %1	leaving sti $4
with REG ADDREG
uses CXREG={ANYCON,$1}
  gen sal %1,cl
      add %2,%1			yields %2	leaving sti $4

pat loc sli ads $2==2 && $3==2
with exact rmorconst ADDR_EXTERN
uses reusing %1,ADDREG=%1,CXREG={ANYCON,$1}
  gen sal %a,cl			yields {Xreg_off,%a,%2.off}
with ADDREG rmorconst
uses CXREG={ANYCON,$1}
  gen sal %1,cl
      add %1,%2			yields %1
with REG ADDREG
uses CXREG={ANYCON,$1}
  gen sal %1,cl
      add %2,%1			yields %2
with REG rmorconst
uses CXREG={ANYCON,$1}
  gen sal %1,cl
      add %1,%2			yields %1

pat aar $1==2
  with AREG ACC
  uses DXREG
  gen sub %2,{ind_reg2,%1}
      mul {ind_regoff2,%1,4}	yields %2	leaving ads 2
  with reg_off ACC
  uses DXREG
  gen sub %2,{ind_regoff2, %1.reg, %1.off}
      mul {ind_regoff2, %1.reg, 4+%1.off}
      				yields %2	leaving ads 2
  with bpreg_off ACC
  uses DXREG
  gen sub %2,{ind_bpregoff2, %1.reg, %1.ind}
      mul {ind_bpregoff2, %1.reg, 4+%1.ind}
				yields %2	leaving ads 2
  with ADDR_LOCAL ACC
  uses DXREG
  gen sub %2,{LOCAL,%1.ind,2}
      mul {LOCAL, 4+%1.ind,2}	yields %2	leaving ads 2
  with ADDR_EXTERN ACC
  uses DXREG
  gen sub %2,{EXTERN2,%1.off}
      mul {EXTERN2,4+%1.off}	yields %2	leaving ads 2

pat lae lar defined(rom($1,3))	leaving lae $1 aar $2 loi rom($1,3)

pat lae sar defined(rom($1,3))  leaving lae $1 aar $2 sti rom($1,3)

pat aar !defined($1)
  kills ALL
  gen joehoe {label,".iaar"}  	yields bx

pat sar $1==2
  with BXREG ACC
  kills ALL
  gen joehoe {label,".sar2"}

pat sar !defined($1)
  kills ALL
  gen joehoe {label,".isar"}

pat lar $1==2 
  with BXREG ACC
  kills ALL
  gen joehoe {label,".lar2"}

pat lar !defined($1)
  kills ALL
  gen joehoe {label,".ilar"}

/*******************************************************************
 *  Group 12 : Compare Instructions                                *
 *******************************************************************/

pat cmi $1==2
with EXACT register rmorconst
  uses REG={ANYCON,0}
  gen cmp %1,%2
      je {label,2f}
      jl {label,1f}
      inc %a
      jmp {label,2f}
      1:
      dec %a
      2:			yields %a
with rmorconst register
  uses REG={ANYCON,0}
  gen cmp %2,%1
      je {label,2f}
      jg {label,1f}
      inc %a
      jmp {label,2f}
      1:
      dec %a
      2:			yields %a

pat cmi $1==4
kills ALL
  gen joehoe {label,".cmi4"}	yields ax

pat cmu $1==2                            leaving cmp

pat cmu $1==4
kills ALL
  gen joehoe {label,".cmu4"}  	yields ax

pat cms $1==2
with EXACT REG rmorconst
  gen sub %1,%2                	yields %1
with rmorconst REG
  gen sub %2,%1                	yields %2

pat cms $1==4
with rmorconst rmorconst REG REG
  gen sub %3,%1
      sbb %4,%2
      or %4,%3			yields %4
with EXACT REG REG rmorconst rmorconst
  gen sub %1,%3
      sbb %2,%4
      or %2,%1			yields %2

pat cms defined($1)
kills ALL
  gen mov cx,{ANYCON,$1}
      joehoe {label,".cms"}     yields cx

pat cms !defined($1)
with CXREG
kills ALL
  gen joehoe {label,".cms"}	yields cx

pat cmf $1==4
kills ALL
  gen joehoe {label,".cmf4"}	leaving asp 8 lfr 2

pat cmf $1==8
kills ALL
  gen joehoe {label,".cmf8"}	leaving asp 16 lfr 2

pat cmp
with EXACT register rmorconst
uses REG = {ANYCON,0}
  gen cmp %1,%2
      je  {label,2f}
      jb  {label,1f}
      inc %a
      jmp {label,2f}
      1: dec %a
      2:                            yields %a
with rmorconst register
uses REG = {ANYCON,0}
  gen cmp %2,%1
      je  {label,2f}
      ja  {label,1f}
      inc %a
      jmp {label,2f}
      1: dec %a
      2:                            yields %a

proc txx
with rm
uses REG = {ANYCON,0}
  gen test %1
      jxx* {label,1f}
      inc %a
      1:                            yields %a

pat tlt call txx("jge")
pat tle call txx("jg")
pat teq call txx("jne")
pat tne call txx("je")
pat tge call txx("jl")
pat tgt call txx("jle")

proc txxior
with rm REG
  gen test %1
      jxx* {label,1f}
      or  %2,{ANYCON,1}
      1:                            yields %2

pat tlt ior $2==2 call txxior("jge")
pat tle ior $2==2 call txxior("jg")
pat teq ior $2==2 call txxior("jne")
pat tne ior $2==2 call txxior("je")
pat tge ior $2==2 call txxior("jl")
pat tgt ior $2==2 call txxior("jle")

proc cmixxior
with regorconst rm REG
  gen cmp %2,%1
      jxx* {label,1f}
      or  %3,{ANYCON,1}
      1:                            yields %3

pat cmi tlt ior $1==2 && $3==2 call cmixxior("jge")
pat cmi tle ior $1==2 && $3==2 call cmixxior("jg")
pat cmi teq ior $1==2 && $3==2 call cmixxior("jne")
pat cmi tne ior $1==2 && $3==2 call cmixxior("je")
pat cmi tge ior $1==2 && $3==2 call cmixxior("jl")
pat cmi tgt ior $1==2 && $3==2 call cmixxior("jle")

proc cmxtxx
with regorconst rm
uses REG = {ANYCON,0}
  gen cmp %2,%1
      jxx[1] {label,1f}
      inc %a
      1:                            yields %a
with rm regorconst
uses REG = {ANYCON,0}
  gen cmp %1,%2
      jxx[2] {label,1f}
      inc %a
      1:                            yields %a

pat cmi tlt $1==2     call cmxtxx("jge","jle")
pat cmi tle $1==2     call cmxtxx("jg","jl")
pat cmi teq $1==2     call cmxtxx("jne","jne")
pat cmi tne $1==2     call cmxtxx("je","je")
pat cmi tge $1==2     call cmxtxx("jl","jg")
pat cmi tgt $1==2     call cmxtxx("jle","jge")
pat cmp tlt           call cmxtxx("jae","jbe")
pat cmp tle           call cmxtxx("ja","jb")
pat cmp teq           call cmxtxx("jne","jne")
pat cmp tne           call cmxtxx("je","je")
pat cmp tge           call cmxtxx("jb","ja")
pat cmp tgt           call cmxtxx("jbe","jae")
pat cms teq $1==2     call cmxtxx("jne","jne")
pat cms tne $1==2     call cmxtxx("je","je")

proc cmxzxx example cmp zlt
with regorconst rm STACK
  gen cmp %2,%1
      jxx[1] {label,$2}
with rm regorconst STACK
  gen cmp %1,%2
      jxx[2] {label,$2}

pat cmp zlt         call cmxzxx("jb","ja")
pat cmp zle         call cmxzxx("jbe","jae")
pat cmp zeq         call cmxzxx("je","je")
pat cmp zne         call cmxzxx("jne","jne")
pat cmp zge         call cmxzxx("jae","jbe")
pat cmp zgt         call cmxzxx("ja","jb")
pat cms zeq $1==2   call cmxzxx("je","je")
pat cms zne $1==2   call cmxzxx("jne","jne")

proc cmx4zxx example cmi zlt
with regorconst regorconst rm rm STACK
  gen cmp %4,%2
      jxx[1] {label,$2}
      jne {label,1f}
      cmp %3,%1
      jxx[2] {label,$2}
      1:
with rm rm regorconst regorconst STACK
  gen cmp %2,%4
      jxx[3] {label,$2}
      jne {label,1f}
      cmp %1,%3
      jxx[4] {label,$2}
      1:

pat cmi zlt $1==4	call cmx4zxx("jl", "jb", "jg", "ja")
pat cmi zle $1==4	call cmx4zxx("jl", "jbe", "jg", "jae")
pat cmi zgt $1==4	call cmx4zxx("jg", "ja", "jl", "jb")
pat cmi zge $1==4	call cmx4zxx("jg", "jae", "jl", "jbe")

pat cmu zlt $1==4	call cmx4zxx("jb", "jb", "ja", "ja")
pat cmu zle $1==4	call cmx4zxx("jb", "jbe", "ja", "jae")
pat cmu zgt $1==4	call cmx4zxx("ja", "ja", "jb", "jb")
pat cmu zge $1==4	call cmx4zxx("ja", "jae", "jb", "jbe")

pat ldc cmi zlt highw($1)==0 && loww($1)==0 && $2==4
with rmorconst rmorconst	yields %2	leaving zlt $3

pat ldc cmi tlt highw($1)==0 && loww($1)==0 && $2==4
with rmorconst rmorconst	yields %2	leaving tlt

pat ldc cmi zge highw($1)==0 && loww($1)==0 && $2==4
with rmorconst rmorconst	yields %2	leaving zge $3

pat ldc cmi tge highw($1)==0 && loww($1)==0 && $2==4
with rmorconst rmorconst	yields %2	leaving tge $3

pat ldc cmi tle highw($1)==0 && loww($1)==0 && $2==4
with rmorconst rmorconst
uses REG = {ANYCON, 0}
  gen cmp %a,%2
      jg {label,2f}
      jl {label,1f}
      cmp %a,%1
      jne {label,1f}
      2:
      inc %a
      1:			yields %a

pat ldc cmi tgt highw($1)==0 && loww($1)==0 && $2==4
with rmorconst rmorconst
uses REG = {ANYCON, 0}
  gen cmp %a,%2
      jl {label,2f}
      jg {label,1f}
      cmp %a,%1
      je {label,1f}
      2:
      inc %a
      1:			yields %a

pat loc ldc cms zeq $3==4 && $1==0 && loww($2)==0 && highw($2)==0
with REG STACK
  gen test %1
      je {label,$4}

pat loc ldc cms zne $3==4 && $1==0 && loww($2)==0 && highw($2)==0
with REG STACK
  gen test %1
      jne {label,$4}

pat loc ldc cms teq $3==4 && $1==0 && loww($2)==0 && highw($2)==0
with REG
uses REG = {ANYCON, 0}
  gen test %1
      jne {label,1f}
      inc %a
      1:			yields %a

pat loc ldc cms tne $3==4 && $1==0 && loww($2)==0 && highw($2)==0
with REG
  gen test %1
      je {label,1f}
      mov %1,{ANYCON,1}
      1:			yields %1

pat ldc cms zeq $2==4 && loww($1)==0 && highw($1)==0
with rmorconst REG STACK
  gen or %2,%1
      je {label,$3}
with REG rmorconst STACK
  gen or %1,%2
      je {label,$3}

pat ldc cms zne $2==4 && loww($1)==0 && highw($1)==0
with rmorconst REG STACK
  gen or %2,%1
      jne {label,$3}
with REG rmorconst STACK
  gen or %1,%2
      jne {label,$3}

pat ldc cms teq $2==4 && loww($1)==0 && highw($1)==0
with rmorconst REG
uses REG = {ANYCON, 0}
  gen or %2,%1
      jne {label,1f}
      inc %a
      1:			yields %a
with REG rmorconst
uses REG = {ANYCON, 0}
  gen or %1,%2
      jne {label,1f}
      inc %a
      1:			yields %a

pat ldc cms tne $2==4 && loww($1)==0 && highw($1)==0
with rmorconst REG
  gen or %2,%1
      je {label,1f}
      mov %2,{ANYCON,1}
      1:			yields %2
with REG rmorconst
  gen or %1,%2
      je {label,1f}
      mov %1,{ANYCON,1}
      1:			yields %1

pat ldc cms zeq $2==4 && loww($1)==65535 && highw($1)==(0-1)
with rmorconst REG STACK
  gen and %2,%1
      cmp %2,{ANYCON,0-1}
      je {label,$3}
with REG rmorconst STACK
  gen and %1,%2
      cmp %1,{ANYCON,0-1}
      je {label,$3}

pat ldc cms zne $2==4 && loww($1)==65535 && highw($1)==(0-1)
with rmorconst REG STACK
  gen and %2,%1
      cmp %2,{ANYCON,0-1}
      jne {label,$3}
with REG rmorconst STACK
  gen and %1,%2
      cmp %1,{ANYCON,0-1}
      jne {label,$3}

pat cms zne $1==4
with regorconst regorconst rm rm STACK
  gen cmp %3,%1
      jne {label,$2}
      cmp %4,%2
      jne {label,$2}
with rm rm regorconst regorconst STACK
  gen cmp %1,%3
      jne {label,$2}
      cmp %2,%4
      jne {label,$2}

pat cms zeq $1==4
with regorconst regorconst rm rm STACK
  gen cmp %3,%1
      jne {label, 1f}
      cmp %4,%2
      je {label,$2}
      1:
with rm rm regorconst regorconst STACK
  gen cmp %1,%3
      jne {label,1f}
      cmp %2,%4
      je {label,$2}
      1:

proc andzxx example and zeq
with regorconst rm STACK
  gen check %2,%1
      jxx* {label,$2}
with exact rm regorconst
  kills ALL
  gen check %1,%2
      jxx* {label,$2}

pat and zeq $1==2 call andzxx("je")
pat and zne $1==2 call andzxx("jne")

proc locandzxx example loc and zeq
with rm12 STACK
  gen testb %1,{ANYCON,$1}
      jxx* {label,$3}
with GENREG STACK
  gen testb %1.1,{ANYCON,$1}
      jxx* {label,$3}
with exact IREG
  kills ALL
  gen check %1,{ANYCON,$1}
      jxx* {label,$3}

pat loc and zeq $1<256 && $1>=0 && $2==2 call locandzxx("je")
pat loc and zne $1<256 && $1>=0 && $2==2 call locandzxx("jne")

proc locbxx example loc beq
with rm1 STACK
  gen cmpb %1,{ANYCON,$1}
      jxx* {label,$2}
with rm STACK
  gen cmp %1,{ANYCON,$1}
      jxx* {label,$2}

pat loc beq $1<256 && $1>=0 call locbxx("je")
pat loc bne $1<256 && $1>=0 call locbxx("jne")

proc loccmuzxx example loc cmu zeq
with rm1 STACK
  gen cmpb %1,{ANYCON,$1}
      jxx* {label,$3}
with rm STACK
  gen cmp %1,{ANYCON,$1}
      jxx* {label,$3}

pat loc cmu zeq $1<256 && $1>=0 && $2==2 call loccmuzxx("je")
pat loc cmu zne $1<256 && $1>=0 && $2==2 call loccmuzxx("jne")

/*******************************************************************
 *  Group 13 : Branch Instructions                                 *
 *******************************************************************/

pat lab topeltsize($1)==2 && !fallthrough($1)
  with STACK
  kills ALL
  gen labeldef $1                 yields ax

pat lab topeltsize($1)==2 && fallthrough($1)
  with ACC STACK
  kills ALL
  gen labeldef $1                 yields ax

pat lab topeltsize($1)!=2
  with STACK
  kills ALL
  gen labeldef $1

pat bra topeltsize($1)==2
  with ACC STACK
  gen jmp {label,$1}

pat bra topeltsize($1)!=2
  with STACK
  gen jmp {label,$1}

proc bxx example blt
with regorconst rm STACK
  gen cmp %2,%1
      jxx[1] {label,$1}
with rm regorconst STACK
  gen cmp %1,%2
      jxx[2] {label,$1}

pat blt		call bxx("jl","jg")
pat ble		call bxx("jle","jge")
pat bge		call bxx("jge","jle")
pat bgt		call bxx("jg","jl")

proc bex example beq
with regorconst rm STACK
  gen cmp %2,%1
      jxx[1] {label,$1}
with rm regorconst STACK
  gen cmp %1,%2
      jxx[2] {label,$1}
with exact rm1 REG1
  kills ALL
  gen cmpb %1,%2
      jxx[2] {label,$1}
with exact REG1 rm1
  kills ALL
  gen cmpb %2,%1
      jxx[1] {label,$1}

pat beq		call bex("je","je")
pat bne		call bex("jne","jne")

proc zxx example zlt
with rm STACK
  gen test %1
      jxx* {label,$1}

pat zlt		call zxx("jl")
pat zle		call zxx("jle")
pat zge		call zxx("jge")
pat zgt		call zxx("jg")

pat zne
with rm+rm1 STACK
  gen test %1
      jne {label,$1}

pat zeq
with rm+rm1 STACK
  gen test %1
      je {label,$1}


/*******************************************************************
 *  Group 14 : Procedure-call Instructions                         *
 *******************************************************************/

pat cal
  kills ALL
  gen joehoe {label,$1}

pat cai
  with rm
  kills ALL
  gen joehoe %1

#ifdef REGVARS
pat lfr adi stl $1==2 && $2==2 && inreg($3) > 0
  kills ALL
  gen pop {LOCAL,$3,2}
      add {LOCAL,$3,2}, ax
#endif

pat lfr $1==2			yields ax

pat lfr $1==4			yields dx ax

pat lfr $1==6
kills ALL
  gen joehoe {label, ".lfr6"}

pat lfr $1==8
kills ALL
  gen joehoe {label, ".lfr8"}

pat ret $1==0
  kills ALL
  gen
#ifdef REGVARS
	return
#else
      mov sp,bp
      pop bp
      ret.
#endif

pat ret $1==2
  with ACC
  kills ALL
  gen
#ifdef REGVARS
	return
#else
      mov sp,bp
      pop bp
      ret.
#endif

pat ret $1==4
  with ACC DXREG
  kills ALL
  gen
#ifdef REGVARS
	return
#else
      mov sp,bp
      pop bp
      ret.
#endif

pat ret $1==6
  with STACK
  gen joehoe {label, ".ret6"}
#ifdef REGVARS
	return
#else
      mov sp,bp
      pop bp
      ret.
#endif

pat ret $1==8
  with STACK
  gen joehoe {label, ".ret8"}
#ifdef REGVARS
	return
#else
      mov sp,bp
      pop bp
      ret.
#endif

/********************************************************************
 *  Group 15 : Miscellaneous Instructions                           *
 ********************************************************************/

pat asp $1==2
with exact a_word
with STACK
  uses BXREG /* GENREG may contain lfr area */
  gen pop %a

pat asp $1==4
with exact a_word a_word
with STACK
  uses BXREG /* GENREG may contain lfr area */
  gen pop %a
      pop %a

pat asp $1==0-2
with STACK                                      yields bp

pat asp
with STACK
  gen add sp,{ANYCON,$1}

pat ass $1==2
with rmorconst STACK
  gen add sp,%1

pat ass !defined($1)
with rm rmorconst STACK
  gen cmp %1,{ANYCON,2}
      jne {label, ".unknown"}
      add sp,%2

pat blm $1==0					leaving asp 4

pat blm $1>0
kills ALL
  gen mov cx,{ANYCON,$1/2}
      joehoe {label, ".blm"}

pat bls $1==2
with CXREG
kills ALL
  gen sar cx,{ANYCON,1}
      joehoe {label, ".blm"}

pat bls !defined($1)
with rm-CXREG CXREG
kills ALL
  gen cmp %1,{ANYCON,2}
      jne {label, ".unknown"}
      sar cx,{ANYCON,1}
      joehoe {label, ".blm"}

pat csa $1==2
with BXREG ACC
kills ALL
  gen jmp {label, ".csa2"}

pat csa $1==4
with BXREG ACC DXREG
kills ALL
  gen jmp {label, ".csa4"}

/*
pat csa !defined($1)
with rm-BXREG-ACC ACC
kills ALL
  gen cmp %1,{ANYCON,2}
      jne {label, ".unknown"}
      jmp {label, ".csa2"}
*/

pat csb $1==2
with BXREG ACC
kills ALL
  gen jmp {label, ".csb2"}

pat csb $1==4
with BXREG ACC DXREG
kills ALL
  gen jmp {label, ".csb4"}

/*
pat csb !defined($1)
with rm-BXREG-ACC BXREG ACC
  gen cmp %1,{ANYCON,2}
      jne {label, ".unknown"}
      jmp {label, ".csb2"}
*/

pat dup $1==2
with anyreg				yields %1 %1
with ACC1				yields %1 %1

pat dup $1==4
with regorconst regorconst		yields %2 %1 %2 %1

pat dup
kills ALL
  gen mov cx,{ANYCON,$1}
      joehoe {label, ".dup"}

pat dus $1==2
with CXREG
kills ALL
  gen joehoe {label, ".dup"}

pat dus !defined($1)
with rm-CXREG CXREG
kills ALL
  gen cmp %1,{ANYCON,2}
      jne {label, ".unknown"}
      joehoe {label, ".dup"}

pat exg $1==2
with a_word a_word			yields %1 %2

pat exg $1==4
with a_word a_word a_word a_word	yields %2 %1 %4 %3

pat exg defined($1)
kills ALL
  gen mov cx,{ANYCON,$1}
      joehoe {label, ".exg"}

pat exg
with CXREG
  kills ALL
  gen joehoe {label, ".exg"}

pat gto
kills ALL
  gen mov bx,{ADDR_EXTERN,$1}
      jmp {label, ".gto"}

pat fil
  gen mov {EXTERN2,"hol0+4"},{ADDR_EXTERN,$1}

pat lim
  uses REG
  gen mov %a,{EXTERN2,".ignmask"}			yields %a

pat lin
  gen mov {EXTERN2,"hol0"},{ANYCON,$1}

pat lni
  gen inc {EXTERN2,"hol0"}

pat lor $1==0				yields bp

pat lor $1==1
with STACK
  uses REG
  gen mov %a,sp				yields %a

pat lor $1==2
  uses REG
  gen mov %a,{EXTERN2,".reghp"}		yields %a

pat mon
with ACC
kills ALL
  gen joehoe {label, ".mon"}

pat nop
kills ALL
#if 0
  gen joehoe {label, ".nop"}
#endif

pat rck $1==2
with BXREG ACC
kills ALL
  gen joehoe {label, ".rck"}				yields ax

pat rck !defined($1)
with rm-BXREG-ACC BXREG ACC
kills ALL
  gen cmp %1,{ANYCON,2}
      jne {label, ".unknown"}
      joehoe {label, ".rck"}				yields ax

pat rtt						leaving ret 0

pat sig
with REG
  gen xchg {EXTERN2,".trppc"},%1			yields %1

pat sim
with regorconst
  gen mov {EXTERN2,".ignmask"},%1

pat str $1==0
with rmorconst
  gen mov bp,%1

pat str $1==1
with rmorconst STACK
  gen mov sp,%1

pat str $1==2
kills ALL
  gen joehoe {label, ".strhp"}

pat trp
with ACC
kills ALL
  gen joehoe {label, ".Xtrp"}