/****************************************************************************
 *            ACK backend for Acorn Risc Machine                            *
 *            First version: A.N.Other, Vrije Universiteit, Amsterdam       *
 *            Completed by: Albert Koelmans, University of Newcastle        *
 *            Register variables by Jonathan Hardwick                       *
 *            With help from: Andy Michael and Ceriel Jacobs                *
 ****************************************************************************/

#define legal(a)     ((a&~0xFF)==0||(a&~0x3FC)==0||(a&~0xFF0)==0||\
 		     (a&~0x3FC0)==0||(a&~0xFF00)==0||(a&~0x3FC00)==0||\
 		     (a&~0xFF000)==0||(a&~0x3FC000)==0||(a&~0xFF0000)==0||\
 		     (a&~0x3FC0000)==0||(a&~0xFF00000)==0||(a&~0x3FC00000)==0||\
 		     (a&~0xFF000000)==0||(a&~0xFC000003)==0||(a&~0xF000000F)==0||\
 		     (a&~0xC000003F)==0||(~a&~0xFF)==0)
#define neglegal(a)  (((0-a)&~0xFF)==0||((0-a)&~0x3FC)==0||((0-a)&~0xFF0)==0||\
 		     ((0-a)&~0x3FC0)==0||((0-a)&~0xFF00)==0||((0-a)&~0x3FC00)==0||\
 		     ((0-a)&~0xFF000)==0||((0-a)&~0x3FC000)==0||((0-a)&~0xFF0000)==0||\
 		     ((0-a)&~0x3FC0000)==0||((0-a)&~0xFF00000)==0||((0-a)&~0x3FC00000)==0||\
 		     ((0-a)&~0xFF000000)==0||((0-a)&~0xFC000003)==0||((0-a)&~0xF000000F)==0||\
 		     ((0-a)&~0xC000003F)==0||(~(0-a)&~0xFF)==0)

#define illegal(a)    !legal(a)
#define minlegal(a)    (a < 0) && neglegal(a)
#define minillegal(a)  (a < 0) && !neglegal(a)

EM_WSIZE=4
EM_PSIZE=4
EM_BSIZE=8

PROPERTIES

GENREG			/* All 16 user registers */
REG			/* Allocatable registers */
PCPSR			/* PSW and PC */
SREG
STACKPOINTER
LOCALBASE
LINKREGISTER

REGISTERS

R0,R1,R2,R3,R8,R9,R10			:GENREG, REG .
R4,R5,R6,R7				:GENREG regvar(reg_any).
R11	               			:GENREG, SREG  .
SP("R12")				:STACKPOINTER .
LB("R13")				:LOCALBASE .
LR("R14")				:LINKREGISTER .
PC("R15")				:PCPSR .

TOKENS

const4		= { INT num; } 4 cost(0,4) "#" num .
fitcon		= { INT num; } 4 cost(0,4) "#" num .
lb_local	= { INT ind; } 4 "[R13,#" ind "]" .
addr_local	= { INT ind; } 4 .
naddr_local	= { INT ind; } 4 .
absolute	= { ADDR add; } 4 add .
addr_external	= { ADDR add; } 4 add .
label		= { ADDR add; } 4 add .
autoid		= { STACKPOINTER reg; } 4 reg "<" .
regexp		= { INT exp;} 4 exp  .
register	= { GENREG exp;} 4 exp  .

imS		= { GENREG reg; ADDR S; INT shift;} 4 
			reg "," S "#" shift  .
regS		= { GENREG reg; ADDR S; GENREG sreg;} 4 
			reg "," S " "sreg  .
regind		= { GENREG reg; } 4 
			"[" reg "]" .
REGrel		= { REG reg; ADDR ind; } 4 
			"[" reg ",#" ind "]"  .
regrel		= { GENREG reg; ADDR ind; } 4 
			"[" reg ",#" ind "]"  .
st_regrel	= { STACKPOINTER reg; ADDR ind; } 4 
			"[" reg ",#" ind "]"  .
lb_regrel	= { LOCALBASE reg; ADDR ind; } 4 
			"[" reg ",#" ind "]"  .
regregrel	= { GENREG reg1; GENREG reg2; } 4 
			"[" reg1 "," reg2 "]" .
st_regregrel	= { STACKPOINTER reg1; GENREG reg2; } 4 
			"[" reg1 "," reg2 "]" .
lb_regregrel	= { LOCALBASE reg1; GENREG reg2; } 4 
			"[" reg1 "," reg2 "]" .
regminregrel	= { GENREG reg1; GENREG reg2; } 4 
			"[" reg1 ",-" reg2 "]" .
regiSregrel	= { GENREG reg1; ADDR S; INT shift; GENREG reg2; } 4
			"[" reg1 "," reg2 ","  S "#" shift "]" .
st_regiSregrel	= { STACKPOINTER reg1; ADDR S; INT shift; GENREG reg2; } 4
			"[" reg1 "," reg2 ","  S "#" shift "]" .
regminiSregrel	= { GENREG reg1; ADDR S; INT shift; GENREG reg2; } 4
			"[" reg1 ",-" reg2 ","  S "#" shift "]" .
regminrSregrel	= { GENREG reg1; ADDR S; GENREG sreg; GENREG reg2; } 4
			"[" reg1 ",-" reg2 ","  S " " sreg "]" .
regrelpi	= { GENREG reg; ADDR ind; } 4 
			"[" reg "],#" ind .
regconst	= { GENREG reg; INT  ind; } 4 
			reg ",#" ind  .

regplusreg	= {GENREG reg1; GENREG reg2;} 4
			reg1 "," reg2 .
regplusiSreg	= {GENREG reg1; ADDR S; INT shift; GENREG reg2;} 4
			reg1 "," reg2 "," S "#" shift .
regplusrSreg	= {GENREG reg1; ADDR S; GENREG sreg; GENREG reg2;} 4
			reg1 "," reg2 "," S "," sreg .
regminreg	= {GENREG reg1; GENREG reg2;} 4
			reg1 "," reg2 .
regminiSreg	= {GENREG reg1; ADDR S; INT shift; GENREG reg2;} 4
			reg1 "," reg2 "," S "#" shift .
regminrSreg	= {GENREG reg1; ADDR S; GENREG sreg; GENREG reg2;} 4
			reg1 "," reg2 "," S "," sreg .

REGlist1	= {REG reg1; } 4 
			"{" reg1 "}" .
reglist1	= {GENREG reg1; } 4 
			"{" reg1 "}" .
lb_reglist1	= {LOCALBASE reg1; } 4 
			"{" reg1 "}" .
sp_reglist1	= {STACKPOINTER reg1; } 4 
			"{" reg1 "}" .
reglist2	= {GENREG reg1; GENREG reg2; } 8 
			"{" reg1 "," reg2 "}" .
lb_pc_reglist2	= {LOCALBASE reg1; PCPSR reg2; } 8 
			"{" reg1 "," reg2 "}" .
reglist3	= {GENREG reg1; GENREG reg2; GENREG reg3; } 12
			"{" reg1 "," reg2 "," reg3 "}" .
reglist4	= {GENREG reg1; GENREG reg2; GENREG reg3; GENREG reg4; } 16
			"{" reg1 "," reg2 "," reg3 "," reg4 "}" .

/* the next 5 are not currently used - perhaps later */
regrelwb	= { GENREG reg; ADDR ind; } 4 "[" reg ",#" ind "]<"  .
regregrelwb	= { GENREG reg1; GENREG reg2; } 4 "[" reg1 "," reg2 "]<" .
regiSregrelwb	= { GENREG reg1; ADDR S; INT shift; GENREG reg2; } 4
			"[" reg1 "," reg2 ","  S "#" shift "]<" .
regrSregrelwb	= { GENREG reg1; ADDR S; GENREG sreg; GENREG reg2; } 4
			"[" reg1 "," reg2 ","  S " " sreg "]<" .
regregrelpi	= { GENREG reg1; GENREG reg2; } 4 "[" reg1 "]," reg2 .

LOCAL		= { INT ind;} 4 ">>> BUG IN LOCAL".
stack		= { GENREG r;} 4 "R12<,{" r "}".

/* tokens to put shifts and rotates into opcodes			*/
reglslcon	= {GENREG target; INT shift;} 4 target ",LSL#" shift.
reglsrcon	= {GENREG target; INT shift;} 4 target ",LSR#" shift.
regasrcon	= {GENREG target; INT shift;} 4 target ",ASR#" shift.
regrorcon	= {GENREG target; INT shift;} 4 target ",ROR#" shift.
reglslreg	= {GENREG target; GENREG shift;} 4 cost(0,1) target ",LSL " shift.
reglsrreg	= {GENREG target; GENREG shift;} 4 cost(0,1) target ",LSR " shift.
regasrreg	= {GENREG target; GENREG shift;} 4 cost(0,1) target ",ASR " shift.
regrorreg	= {GENREG target; GENREG shift;} 4 cost(0,1) target ",ROR " shift.
regrorregr	= {GENREG target; GENREG shift;} 4 cost(0,1) target ",ROR " shift.


SETS

address		= absolute + regind + regrel + regrelwb + regregrel +
		  st_regrel + st_regregrel + st_regiSregrel +
		  lb_regrel + lb_regregrel +
                  regiSregrel + regiSregrelwb + regrSregrelwb +
		  regminregrel + regminiSregrel + regminrSregrel +
		  regregrelwb + regrelpi + regregrelpi + lb_local .
REGcon		= GENREG + imS + regS + fitcon  .
reglist		= reglist1 + reglist2 + reglist3 + reglist4 +
		  lb_reglist1 + sp_reglist1 + lb_pc_reglist2 +
		  regexp + REGlist1 .
constant        = fitcon + const4 .
local		= lb_local + LOCAL.
regshift	= reglslreg + reglsrreg + regasrreg + regrorreg + regrorregr +
		  reglslcon + reglsrcon + regasrcon + regrorcon.
rhs		= GENREG + constant + regshift + LOCAL.
mem4		= regregrel + regrel + lb_local.
extern		= addr_external + absolute + label.
all_except_con  = mem4 + extern + local.
any_data	= all_except_con + rhs.
any_data_except_local = any_data - LOCAL.
posshifts       = regplusiSreg+regplusrSreg.
negshifts       = regminiSreg+regminrSreg.
shifts          = posshifts+negshifts.

INSTRUCTIONS

BAL  		 label  					cost(4,4) .
BAL_L   "BAL.L"  label 						cost(4,4) .
BAL_LEQ "BAL.L.EQ" label 					cost(4,4) .
BNV  		 label 						cost(4,4) .
BNE  		 label 						cost(4,4) .
BEQ  		 label 						cost(4,4) .
BMI  		 label 						cost(4,4) .
BGT  		 label 						cost(4,4) .
BLT  		 label 						cost(4,4) .
BLE  	 	 label 						cost(4,4) .
BGE  		 label 						cost(4,4) .

LDR  		 REG+LOCALBASE+GENREG+address:wo, address:rw 	cost(4,4) .
LDR		 LOCAL+GENREG:rw,
			mem4+absolute+addr_external:ro		cost(4,4) .
STR  		 GENREG+REG:ro, REGrel+address:rw 		cost(4,4) .
LDR_B  "LDR.B"   REG+GENREG:wo, address:rw 			cost(4,4) .
LDR_B		 LOCAL:rw, rhs+mem4:ro				cost(4,4) .
STR_B  "STR.B"   GENREG+REG:ro, address:rw 			cost(4,4) .

LDMFD 		 autoid:rw, reglist:wo 				cost(4,7) .
STMFD 		 autoid:rw, reglist:ro 				cost(4,7) .
STMFD		 stack						cost(4,4) .
LDMIA 		 GENREG:rw, reglist:wo 				cost(4,7) .

ADC  		 REG+GENREG:wo, REG+GENREG:ro, REGcon:ro  	cost(4,1) .
ADD  		 GENREG+REG:wo, GENREG:ro, REGcon+const4:ro  	cost(4,1) .
ADD  		 GENREG+STACKPOINTER:wo, GENREG+STACKPOINTER:ro,
			STACKPOINTER+REGcon+const4:ro  		cost(4,1) .
ADD  		 LOCAL+GENREG+REG:wo,
			regconst+shifts+regminreg+regplusreg:ro	cost(4,1) .
ADD		 LOCAL+GENREG:rw, LOCALBASE+GENREG+LOCAL:ro,
					rhs:ro			cost(4,1).
ADD_NE "ADD.NE"  GENREG+REG:wo, GENREG:ro, REGcon+const4:ro  	cost(4,1) .
AND  		 REG+GENREG:wo, GENREG:ro, GENREG+REGcon:ro  	cost(4,1) .
AND_S  "AND.S"   GENREG+REG:wo, GENREG:ro, REGcon:ro  		cost(4,1) .
BIC  		 REG+GENREG:wo, GENREG:ro, REGcon:ro  		cost(4,1) .
CMN  		 GENREG+REG:ro, REGcon:ro kills :cc  		cost(4,1) .
CMP  		 REG+GENREG:ro, REGcon:ro kills :cc  		cost(4,1) .
EOR  		 GENREG+REG:wo, GENREG:ro, GENREG+REGcon:ro	cost(4,1) .
EOR_S  "EOR.S"   REG+GENREG:wo:cc, GENREG:ro, REGcon:ro  	cost(4,1) .
MOV  		 REG:wo, REGcon+const4:ro  			cost(4,1) .
MOV		 REG:rw, LOCAL:ro				cost(4,1).
MOV		 LOCALBASE+PCPSR+STACKPOINTER+GENREG:rw, 
		 REGcon+address+LOCALBASE+PCPSR+
				STACKPOINTER+GENREG+LOCAL:ro	cost(4,1).
MOV		 LOCAL+GENREG:rw, GENREG+rhs+register+REG:ro	cost(4,1).
MOV  		 LOCALBASE+GENREG:wo, REGcon+const4:ro  	cost(4,1) .
MOV_MI "MOV.MI"  REG+GENREG:wo, REGcon+const4:ro  		cost(4,1) .
MOV_HI "MOV.HI"  GENREG+REG:wo, REGcon+const4:ro  		cost(4,1) .
MOV_LS "MOV.LS"  REG+GENREG:wo, REGcon+const4:ro  		cost(4,1) .
MOV_LT "MOV.LT"  GENREG+REG:wo, REGcon+const4:ro  		cost(4,1) .
MOV_LE "MOV.LE"  REG+GENREG:wo, REGcon+const4:ro  		cost(4,1) .
MOV_EQ "MOV.EQ"  GENREG+REG:wo, REGcon+const4:ro  		cost(4,1) .
MOV_NE "MOV.NE"  REG+GENREG:wo, REGcon+const4:ro  		cost(4,1) .
MOV_GE "MOV.GE"  REG+GENREG:wo, REGcon+const4:ro  		cost(4,1) .
MOV_GT "MOV.GT"  REG+GENREG:wo, REGcon+const4:ro  		cost(4,1) .
MOV_NV "MOV.NV"  GENREG+REG:wo, REGcon+const4:ro  		cost(4,1) .
MOV_S  "MOV.S"   GENREG+REG:wo, REGcon+const4+regind:ro
						kills :cc   	cost(4,1) .
MVN  		 LOCAL+GENREG+REG:wo, REGcon:ro			cost(4,1) .
ORR  		 REG+GENREG:wo, GENREG:ro, GENREG+REGcon:ro	cost(4,1) .
ORR  		 REG+GENREG+LOCAL:wo, imS:ro			cost(4,1) .
RSB		 REG+GENREG+LOCAL:rw, REG+GENREG+LOCAL:ro,
					rhs:ro			cost(4,1).
RSB  		 GENREG+REG:wo, GENREG:ro, REGcon:ro  		cost(4,1) .
RSB_S  "RSB.S"   REG+GENREG:wo:cc, GENREG:ro, REGcon:ro  	cost(4,1) .
RSC  		 GENREG+REG:wo, GENREG:ro, REGcon:ro  		cost(4,1) .
SBC  		 REG+GENREG:wo, GENREG:ro, REGcon:ro  		cost(4,1) .
SUB		 LOCAL+GENREG:rw,
			regconst+shifts+regplusreg+regminreg:ro	cost(4,1).
SUB		 LOCAL:rw, LOCAL:ro, rhs:ro			cost(4,1).
SUB  		 LOCAL+REG+GENREG:wo, LOCALBASE+GENREG:ro, 
			constant+REGcon:ro  			cost(4,1) .
SUB_S  "SUB.S"   REG+GENREG:wo:cc, GENREG:ro, REGcon:ro  	cost(4,1) .
TEQ  		 GENREG+REG:ro, REGcon:ro kills :cc  		cost(4,1) .
TST 		 REG+GENREG:ro, REGcon:ro kills :cc  		cost(4,1) .
ADR 		 REG+LINKREGISTER+GENREG:wo,
					addr_external+label:ro	cost(4,1) .
LABEL  "" 	 label kills :cc 				cost(4,1) .

/* Dummy instructions for ncgg procedures : lxx is logical operator,	*/ 
/* mxx is conditional move, bxx is conditional branch, rxx is arith-	*/
/* metical operator on register variable (LOCAL).			*/

lxx "lxx : bug in cg"	REG:rw, REG:ro, rhs:ro 		cost(4,1).
mxx "mxx : bug in cg"	REG:rw, rhs:ro			cost(4,1).
bxx "bxx : bug in cg"	addr_external			cost(4,4).
rxx "rxx : bug in cg"	LOCAL:rw, LOCAL:ro, rhs:ro	cost(4,1).
rrx "rrx : bug in cg"	LOCAL:rw, LOCAL:ro, LOCAL:ro	cost(4,1).


MOVES

from GENREG+STACKPOINTER+LOCALBASE+PCPSR to
     GENREG+STACKPOINTER+LOCALBASE+PCPSR
	gen MOV %2, %1

from fitcon+GENREG+REG to LOCAL inreg(%ind)==reg_any
	gen MOV %2, %1

from LOCAL inreg(%ind)==reg_any to REG+GENREG
	gen MOV %2, %1

/* illegal immediate operands */

from const4 minlegal(%num+1) to GENREG+LOCAL
gen MVN %2, {fitcon, 0-%1.num-1}

from const4 (minlegal(%num)) to GENREG+LOCAL
gen MOV %2, {fitcon, 0-%1.num}
    RSB %2, %2, {fitcon, 0}

from const4 to GENREG+LOCAL    /* general case */
      gen MOV %2,     { fitcon,   %1.num & 0xFF}
          ADD %2, %2, { fitcon,   %1.num & 0xFF00}
          ADD %2, %2, { fitcon,   %1.num & 0xFF0000}
          ADD %2, %2, { fitcon,   %1.num & 0xFF000000}

from regconst (%ind > 0) && legal(%ind) to LOCAL inreg(%ind)==reg_any
	gen ADD %2, %1

from regconst minlegal(%ind) to LOCAL inreg(%ind)==reg_any
	gen SUB %2, %1.reg, {fitcon, 0-%1.ind}

from lb_local legal(%ind) to GENREG
gen LDR %2, {lb_regrel, LB, %1.ind}

from lb_local to GENREG
gen move {const4, %1.ind}, R11
    LDR %2, {lb_regregrel, LB, R11}

from GENREG to lb_local legal(%ind)
gen STR %1, {lb_regrel, LB, %2.ind}

from GENREG to lb_local
gen move {const4, %2.ind}, R11
    STR %1, {lb_regregrel, LB, R11}

from GENREG to address
	gen STR %1, %2

from address to GENREG+LOCALBASE
	gen LDR %2, %1

from GENREG to autoid
	gen STMFD %2, {reglist1, %1}

from autoid to GENREG
	gen LDMFD %1, {reglist1, %2}

from REGcon to GENREG+LOCALBASE
	gen MOV %2, %1


from addr_external to GENREG
          gen ADR %2, %1

/* strictly speaking, the following move is impossible.
 * what it really means is: move from reg to address!
 */
from GENREG to addr_external
          gen ADR R11,%2
              STR %1,{regind,R11}



TESTS

to test GENREG
gen CMP %1, {fitcon, 0}


STACKINGRULES

from LOCAL to STACK
	gen STMFD {stack, regvar(%1.ind)}

from REG to STACK
	gen STMFD {autoid, SP}, {REGlist1, %1}

from GENREG to STACK
	gen STMFD {autoid, SP}, {reglist1, %1}

from LOCALBASE to STACK
	gen STMFD {autoid, SP}, {lb_reglist1, %1}

from STACKPOINTER to STACK
	gen STMFD {autoid, SP}, {sp_reglist1, %1}

from REGcon to STACK
	gen move %1, R11
	    STMFD {autoid, SP}, {reglist1, R11}

from const4 to STACK
	gen move %1, R11
	    STMFD {autoid, SP}, {reglist1, R11}

from addr_local legal(%ind) to STACK
	gen ADD R11, LB, {fitcon, %1.ind}
	    STMFD {autoid, SP}, {reglist1, R11}

from addr_local to STACK
	gen move {const4, %1.ind}, R11
	    ADD R11, LB, R11
	    STMFD {autoid, SP}, {reglist1, R11}

from naddr_local legal(%ind) to STACK
	gen SUB R11, LB, {fitcon, %1.ind}
	    STMFD {autoid, SP}, {reglist1, R11}

from naddr_local to STACK
	gen move {const4, %1.ind}, R11
	    SUB R11, LB, R11
	    STMFD {autoid, SP}, {reglist1, R11}

from addr_external to STACK
	gen ADR R11, %1
	    STMFD {autoid, SP}, {reglist1, R11}

from regconst (%ind > 0) && legal(%ind) to STACK
	gen ADD R11, %1.reg, {fitcon,%1.ind}
	    STMFD {autoid, SP}, {reglist1, R11}

from regconst to STACK
	gen move {const4, %1.ind}, R11
	    ADD R11, R11, %1.reg
	    STMFD {autoid, SP}, {reglist1, R11}

from regplusreg to STACK
	gen ADD R11, %1.reg1, %1.reg2
	    STMFD {autoid, SP}, {reglist1, R11}

from regminreg to STACK
	gen SUB R11, %1.reg1, %1.reg2
	    STMFD {autoid, SP}, {reglist1, R11}

from regplusiSreg to STACK
	gen ADD R11, %1.reg1, {imS, %1.reg2, %1.S, %1.shift}
	    STMFD {autoid, SP}, {reglist1, R11}

from regminiSreg to STACK
	gen SUB R11, %1.reg1, {imS, %1.reg2, %1.S, %1.shift}
	    STMFD {autoid, SP}, {reglist1, R11}

from regplusrSreg to STACK
	gen ADD R11, %1.reg1, {regS, %1.reg2, %1.S, %1.sreg}
	    STMFD {autoid, SP}, {reglist1, R11}

from regminrSreg to STACK
	gen SUB R11, %1.reg1, {regS, %1.reg2, %1.S, %1.sreg}
	    STMFD {autoid, SP}, {reglist1, R11}

from address to STACK
	gen move %1, R11
	    STMFD {autoid, SP}, {reglist1, R11}

COERCIONS

from LOCAL
uses GENREG
gen MOV %a, %1					yields %a

from lb_local legal(%ind)
uses GENREG
gen LDR %a, {lb_regrel, LB, %ind}   		yields %a

from lb_local
uses GENREG
gen move {const4, %ind}, R11 
    LDR %a, {lb_regregrel, LB, R11}   		yields %a

from const4 %num < 0
uses GENREG
	gen move {const4, 0-%num}, %a
	    RSB %a, %a, {fitcon, 0}       	yields %a

from const4 illegal(%num)
uses GENREG
	gen move %1, %a				yields %a

from const4 					yields {fitcon, %num}

from STACK
uses GENREG
	gen LDMFD {autoid, SP}, {reglist1, %a}	yields %a

from address
uses GENREG
	gen move %1, %a				yields %a

from REGcon
uses GENREG
	gen move %1, %a				yields %a

from addr_external
uses GENREG
	gen move %1, %a
	    					yields %a

from addr_local legal(%ind)
uses GENREG
	gen ADD %a, LB, {fitcon, %ind}		yields %a

from addr_local
uses GENREG
	gen move {const4, %ind}, %a
	    ADD %a, LB, %a 			yields %a

from naddr_local legal(%ind)
uses GENREG
	gen SUB %a, LB, {fitcon, %ind}		yields %a

from naddr_local
uses GENREG
	gen move {const4, %ind}, %a
	    SUB %a, LB, %a 			yields %a

from regconst (%ind > 0) && legal(%ind)
uses GENREG
	gen ADD %a, %1				yields %a

from regconst minlegal(%ind)
uses GENREG
	gen SUB %a, %reg, {fitcon, 0-%ind}	yields %a

from regconst minillegal(%ind)
uses GENREG
	gen move {const4, 0-%ind}, %a
	    SUB %a, %a, %reg			yields %a

from regconst
uses GENREG
	gen move {const4, %ind}, %a
	    ADD %a, %a, %reg			yields %a

from regplusreg
uses GENREG
	gen ADD %a, %reg1, %reg2
						yields %a

from regminreg
uses GENREG
	gen SUB %a, %reg1, %reg2
						yields %a

from regplusiSreg
uses GENREG
	gen ADD %a, %reg1, {imS, %reg2, %S, %shift}
						yields %a

from regminiSreg
uses GENREG
	gen SUB %a, %reg1, {imS, %reg2, %S, %shift}
						yields %a

from regplusrSreg
uses GENREG
	gen ADD %a, %reg1, {regS, %reg2, %S, %sreg}
						yields %a

from regminrSreg
uses GENREG
	gen SUB %a, %reg1, {regS, %reg2, %S, %sreg}
						yields %a


PATTERNS

/************************************************************************
 *									*
 * GROUP 0 :	Register variables					*
 *									*
 ************************************************************************/

/* Simple load and store */
pat lol			inreg($1)==reg_any
    yields {LOCAL, $1}

pat lil			inreg($1)==reg_any
    yields {regind, regvar($1)}

pat stl			inreg($1)==reg_any
with exact const4
kills local %ind==$1
gen move %1, {LOCAL, $1}
with exact fitcon
kills local %ind==$1
gen MOV {LOCAL, $1}, %1
with rhs-constant
kills local %ind==$1
	gen MOV {LOCAL, $1}, %1
with mem4+absolute
kills local %ind==$1
	gen LDR {LOCAL, $1}, %1
with regminreg
kills local %ind == $1
	gen SUB {LOCAL, $1}, %1
with regplusreg+posshifts
kills local %ind == $1
	gen ADD {LOCAL, $1}, %1
with negshifts
kills local %ind == $1
	gen SUB {LOCAL, $1}, %1

pat stl	$1==1 && inreg($1)==reg_any
with rhs
    kills local %ind==$1
    gen LDR_B {LOCAL, $1}, %1

pat sil			inreg($1)==reg_any
with GENREG
    kills /*all_except_con*/ address
    gen move %1, {regind, regvar($1)}


/* Increment, decrement, zero						*/
pat inl			inreg($1)==reg_any
    kills local %ind==$1
    gen ADD {LOCAL, $1}, {LOCAL, $1}, {fitcon, 1}

pat del			inreg($1)==reg_any
    kills local %ind==$1
    gen SUB {LOCAL, $1}, {LOCAL, $1}, {fitcon, 1}

pat zrl			inreg($1)==reg_any
    kills local %ind==$1
    gen MOV {LOCAL, $1}, {fitcon, 0}

pat lol inc stl		inreg($1)==reg_any && inreg($3)==reg_any
    kills local %ind==$3
    gen ADD {LOCAL, $3}, {LOCAL, $1}, {fitcon, 1}

pat lol dec stl		inreg($1)==reg_any && inreg($3)==reg_any
    kills local %ind==$3
    gen SUB {LOCAL, $3}, {LOCAL, $1}, {fitcon, 1}

pat lol ngi stl 	inreg($1)==reg_any && inreg($3)==reg_any
    kills local %ind==$3
    gen RSB {LOCAL, $3}, {LOCAL, $1}, {fitcon, 0}

/* Procedure :  load register, op xx, store register */
proc lol_op_stl example lol adi stl
with rhs
    kills local %ind==$3
    gen rxx* {LOCAL, $3}, {LOCAL, $1}, %1

pat lol adi stl		inreg($1)==reg_any && inreg($3)==reg_any && $2==4
    call lol_op_stl("ADD")

pat lol adu stl		leaving lol $1 adi $2 stl $3

pat lol sbi stl		inreg($1)==reg_any && inreg($3)==reg_any && $2==4
    call lol_op_stl("RSB")

pat lol sbu stl		leaving lol $1 sbi $2 stl $3

pat lol and stl		inreg($1)==reg_any && inreg($3)==reg_any && $2==4
    call lol_op_stl("AND")

pat lol ior stl		inreg($1)==reg_any && inreg($3)==reg_any && $2==4
    call lol_op_stl("ORR")

pat lol xor stl		inreg($1)==reg_any && inreg($3)==reg_any && $2==4
    call lol_op_stl("EOR")

/* Procedure : load register, load constant, op xx, store register */
proc lol_loc_op_stl example lol loc adi stl
    kills local %ind==$4
    gen rxx* {LOCAL, $4}, {LOCAL, $1}, {const4, $2}

pat lol loc adi stl	inreg($1)==reg_any && inreg($4)==reg_any && $3==4
    call lol_loc_op_stl("ADD")

pat lol loc adu stl	leaving lol $1 loc $2 adi $3 stl $4

pat lol loc sbi stl	inreg($1)==reg_any && inreg($4)==reg_any && $3==4
    call lol_loc_op_stl("SUB")

pat lol loc sbu stl	leaving lol $1 loc $2 sbi $3 stl $4

pat lol loc and stl	inreg($1)==reg_any && inreg($4)==reg_any && $3==4
    call lol_loc_op_stl("AND")

pat lol loc ior stl	inreg($1)==reg_any && inreg($4)==reg_any && $3==4
    call lol_loc_op_stl("ORR")

pat lol loc xor stl	inreg($1)==reg_any && inreg($4)==reg_any && $3==4
    call lol_loc_op_stl("EOR")

pat lol dup inreg($1)==reg_any && $2==4	leaving lol $1 lol $1

/* Procedure : load register, load register, op xx, store register	*/
proc lol_lol_op_stl example lol lol adi stl
    kills local %ind==$4
    gen	rrx* {LOCAL, $4}, {LOCAL, $1}, {LOCAL, $2}

pat lol lol adi stl	inreg($1)==reg_any && inreg($2)==reg_any && 
			inreg($4)==reg_any && $3==4
    call lol_lol_op_stl("ADD")

pat lol lol adu stl	leaving lol $1 lol $2 adi $3 stl $4

pat lol lol sbi stl	inreg($1)==reg_any && inreg($2)==reg_any && 
			inreg($4)==reg_any && $3==4
    call lol_lol_op_stl("SUB")

pat lol lol sbu stl	leaving lol $1 lol $2 sbi $3 stl $4

pat lol lol and stl	inreg($1)==reg_any && inreg($2)==reg_any && 
			inreg($4)==reg_any && $3==4
    call lol_lol_op_stl("AND")

pat lol lol ior stl	inreg($1)==reg_any && inreg($2)==reg_any && 
			inreg($4)==reg_any && $3==4
    call lol_lol_op_stl("ORR")

pat lol lol xor stl	inreg($1)==reg_any && inreg($2)==reg_any && 
			inreg($4)==reg_any && $3==4
    call lol_lol_op_stl("EOR")

/* Shifts								*/
pat lol loc sli stl	inreg($1)==reg_any && inreg($4)==reg_any && $3==4
    kills local %ind==$4
    gen MOV {LOCAL, $4}, {reglslcon, regvar($1), $2}

pat lol loc slu stl	leaving lol $1 loc $2 sli $3 stl $4

pat lol loc sri stl	inreg($1)==reg_any && inreg($4)==reg_any && $3==4
    kills local %ind==$4
    gen	MOV {LOCAL, $4}, {regasrcon, regvar($1), $2}

pat lol loc sru stl	inreg($1)==reg_any && inreg($4)==reg_any && $3==4
    kills local %ind==$4
    gen	MOV {LOCAL, $4}, {reglsrcon, regvar($1), $2}

pat lol lol sli stl	inreg($1)==reg_any && inreg($2)==reg_any &&
			inreg($4)==reg_any && $3==4
    kills local %ind==$4
    gen MOV {LOCAL, $4}, {reglslreg, regvar($1), regvar($2)}

pat lol lol slu stl	leaving lol $1 lol $2 sli $3 stl $4

pat lol lol sri stl	inreg($1)==reg_any && inreg($2)==reg_any &&
			inreg($4)==reg_any && $3==4
    kills local %ind==$4
    gen MOV {LOCAL, $4}, {regasrreg, regvar($1), regvar($2)}

pat lol lol sru stl	inreg($1)==reg_any && inreg($2)==reg_any &&
			inreg($4)==reg_any && $3==4
    kills local %ind==$4
    gen MOV {LOCAL, $4}, {reglsrreg, regvar($1), regvar($2)}

/* Rotates								*/
pat lol loc ror stl	inreg($1)==reg_any && inreg($4)==reg_any && $3==4
    kills local %ind==$4
    gen	MOV {LOCAL, $4}, {regrorcon, regvar($1), $2}

pat lol lol ror stl	inreg($1)==reg_any && inreg($2)==reg_any && 
			inreg($4)==reg_any && $3==4
    kills local %ind==$4
    gen	MOV {LOCAL, $4}, {regrorreg, regvar($1), regvar($2)}

pat lol loc rol stl	inreg($1)==reg_any && inreg($4)==reg_any && $3==4
    kills local %ind==$4
    gen	MOV {LOCAL, $4}, {regrorcon, regvar($1), 32-$2}

pat lol lol ror stl	inreg($1)==reg_any && inreg($2)==reg_any &&
			inreg($4)==reg_any && $3==4
    kills local %ind==$4
    gen	RSB R11, {LOCAL, $2}, {fitcon, 32}
	MOV {LOCAL, $4}, {regrorregr, regvar($1), R11}

/* code for *p++ and *p-- (integers) */
pat lol lol adp stl loi $1==$2 && $2==$4 && $5==4 && inreg($1)==reg_any
kills GENREG
uses GENREG
gen LDR %a, {regrelpi, regvar($1), $5}    		yields %a

pat lol lol adp stl sti $1==$2 && $2==$4 && $5==4 && inreg($1)==reg_any
with GENREG
kills GENREG
gen STR %1, {regrelpi, regvar($1), $5}

/* code for *p++ and *p-- (bytes)*/
pat lol lol adp stl loi $1==$2 && $2==$4 && $5==1 && inreg($1)==reg_any
kills GENREG
uses GENREG
gen LDR_B %a, {regrelpi, regvar($1), $5}    		yields %a

pat lol lol adp stl sti $1==$2 && $2==$4 && $5==1 && inreg($1)==reg_any
with GENREG
kills GENREG
gen STR_B %1, {regrelpi, regvar($1), $5}

/* code for *pp->p++ and *pp->p-- (integers) */
pat lil dup adp sil loi $1==$4 && $2==4 && $5==4 && inreg($1)==reg_any
kills GENREG
uses GENREG,GENREG
gen LDR %a, {regind, regvar($1)}
    ADD %b, %a, {fitcon, $3}
    STR %b, {regind, regvar($1)}
    LDR %b, {regind, %a}				yields %b

pat lil dup adp sil sti $1==$4 && $2==4 && $5==4 && inreg($1)==reg_any
with GENREG
kills GENREG
uses GENREG,GENREG
gen LDR %a, {regind, regvar($1)}
    ADD %b, %a, {fitcon, $3}
    STR %b, {regind, regvar($1)}
    STR %1, {regind, %a}

/* code for *pp->p++ and *pp->p-- (bytes) */
pat lil dup adp sil loi $1==$4 && $2==4 && $5==1 && inreg($1)==reg_any
kills GENREG
uses GENREG,GENREG
gen LDR %a, {regind, regvar($1)}
    ADD %b, %a, {fitcon, $3}
    STR %b, {regind, regvar($1)}
    LDR_B %b, {regind, %a}				yields %b

pat lil dup adp sil sti $1==$4 && $2==4 && $5==1 && inreg($1)==reg_any
with GENREG
kills GENREG
uses GENREG,GENREG
gen LDR %a, {regind, regvar($1)}
    ADD %b, %a, {fitcon, $3}
    STR %b, {regind, regvar($1)}
    STR_B %1, {regind, %a}

/************************************************************************
 *									*
 * GROUP I :	Load Instructions					*
 *									*
 ************************************************************************/

pat loc $1 < 0						yields {const4, $1}

pat loc legal($1) 					yields {fitcon, $1}

pat loc							yields {const4, $1}

pat ldc	leaving loc 18 trp

pat lol							yields {lb_local, $1}

pat loe							yields {absolute, $1}

pat lil	leaving lol $1 loi 4

pat lof
with GENREG			yields {regrel, %1, $1}
with exact addr_local		yields {lb_local, %1.ind+$1}
with exact addr_external	yields {absolute, %1.add+$1}
with exact regconst		yields {regrel, %1.reg, $1+%1.ind}

pat lal $1 > 0			yields {addr_local, $1}
pat lal $1 < 0			yields {naddr_local, 0-$1}
pat lal $1 == 0			yields LB

pat lae				yields {addr_external, $1}
pat lae loi lae sti $2==$4      leaving lae $1 lae $3 blm $2

pat lxl $1==0			yields LB

pat lxl $1==1			yields {lb_local,8}

pat lxl $1>1
uses GENREG={const4, $1}, GENREG=LB
gen LABEL {label, "1:"}
    move {regrel, %b, 8}, %b
    SUB_S %a, %a, {fitcon,1}
    BNE {label,"1B"}		yields %b

pat lxa $1==0			yields {addr_local,8}

pat lxa $1==1
uses GENREG={lb_local,8}		yields {regconst,%a,8}


pat lxa $1>1
uses GENREG={const4, $1}, GENREG=LB
gen LABEL {label, "1:"}
    move {regrel, %b, 8}, %b
    SUB_S %a, %a, {fitcon,1}
    BNE {label,"1B"}		yields {regconst, %b, 8}

pat loi $1==1
with GENREG
uses GENREG
gen LDR_B %a, {regind, %1}					yields %a
with exact naddr_local
uses GENREG
gen LDR_B %a, {lb_local, 0-%1.ind}				yields %a
with exact addr_local
uses GENREG
gen LDR_B %a, {lb_local, %1.ind}				yields %a
with exact addr_external
uses GENREG
gen LDR_B %a, {absolute, %1.add}				yields %a
with exact regconst
uses GENREG
gen LDR_B %a, {regrel, %1.reg, %1.ind}				yields %a
with exact regplusreg
uses GENREG
gen LDR_B %a, {regregrel, %1.reg1, %1.reg2}			yields %a
with exact regminreg
uses GENREG
gen LDR_B %a, {regminregrel, %1.reg1, %1.reg2}			yields %a
with exact regplusiSreg
uses GENREG
gen LDR_B %a, {regiSregrel, %1.reg1, %1.S, %1.shift, %1.reg2}	yields %a
with exact regminiSreg
uses GENREG
gen LDR_B %a, {regminiSregrel,%1.reg1,%1.S,%1.shift,%1.reg2}	yields %a

with exact regplusrSreg
uses GENREG,GENREG
gen move {regS,%1.reg2,%1.S,%1.sreg}, %b
    LDR_B %a, {regregrel, %1.reg1, %b}				yields %a

with exact regminrSreg
uses GENREG
gen LDR_B %a, {regminrSregrel,%1.reg1,%1.S,%1.sreg,%1.reg2}	yields %a

pat loi $1==2
with GENREG
uses GENREG, GENREG
gen LDR_B %a, {regind, %1}
    LDR_B %b, {regrel, %1, 1}
    ADD %a,%a,{imS,%b,"LSL",8}	yields %a

pat loi $1==4
with GENREG			yields {regind, %1}
with exact addr_local		yields {lb_local, %1.ind}
with exact naddr_local		yields {lb_local, 0-%1.ind}
with exact addr_external	yields {absolute, %1.add}
with exact regconst		yields {regrel, %1.reg, %1.ind}
with exact regplusreg		yields {regregrel, %1.reg1, %1.reg2}
with exact regminreg		yields {regminregrel, %1.reg1, %1.reg2}
with exact regplusiSreg	 	yields {regiSregrel,%1.reg1,%1.S,
						    %1.shift,%1.reg2}
with exact regminiSreg	 	yields {regminiSregrel,%1.reg1,%1.S,
						       %1.shift,%1.reg2}
with exact regplusrSreg
uses GENREG,GENREG
gen move {regS,%1.reg2,%1.S,%1.sreg}, %b
    LDR %a, {regregrel, %1.reg1, %b}		yields %a

with exact regminrSreg	 			yields {regminrSregrel,%1.reg1,
							  %1.S,%1.sreg,%1.reg2}

pat loi $1==8
with GENREG
uses GENREG, GENREG
gen LDMIA %1, {reglist2, %a, %b}		yields %b %a

pat loi defined($1)
with GENREG STACK
uses GENREG = {const4, $1}
gen LABEL {label, "1:"}
    SUB_S %a, %a, {fitcon, 4}
    move {regregrel, %1, %a}, R11
    STMFD {autoid, SP}, {reglist1, R11}
    BGT {label, "1b"}

pat loi loc and $1==2 && $2>0 && $2<256  leaving loi 1 loc $2 and $3

pat loi loc loc cii $1==2 && $2==2 && $3==4
with GENREG
uses GENREG,GENREG
gen LDR_B %a, {regind, %1}
    LDR_B %b, {regrel, %1, 1}
    MOV   %b, {imS, %b, "LSL", 24}
    ORR   %a, %a, {imS, %b, "ASR", 16}			yields %a

pat los
with STACK
kills ALL
gen BAL_L {label, ".los"}

pat ldl				yields {lb_local, $1+4}
					{lb_local, $1}

pat lde				yields {absolute, $1+4}
				       {absolute, $1}

pat ldf
with GENREG			yields {regrel, %1, $1+4}
				       {regrel, %1, $1}
with exact addr_local		yields {lb_local, %1.ind+$1+4}
				       {lb_local, %1.ind+$1}
with exact addr_external	yields {absolute, %1.add+$1+4}
				       {absolute, %1.add+$1}
with exact regconst		yields {regrel, %1.reg, $1+%1.ind+4}
				       {regrel, %1.reg, $1+%1.ind}

pat lpi					yields {addr_external,$1}

/************************************************************************
 *									*
 * GROUP II :	Store Instructions					*
 *									*
 ************************************************************************/

pat stl
with GENREG
kills address-(absolute+lb_local), lb_local %ind-4 < $1 && %ind+4 > $1
	gen move %1, {lb_local, $1}

pat stl lol $1==$2		leaving dup 4 stl $1

pat ste
with GENREG
kills address
	gen move %1, {absolute, $1}

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

pat sil	leaving lol $1 sti 4

pat stf
with GENREG GENREG
kills address
	gen move %2, {regrel, %1, $1}
with addr_local GENREG
kills address
	gen move %2, {lb_local, %1.ind + $1}
with addr_external GENREG
kills address
	gen move %2, {absolute, %1.add + $1}
with regconst GENREG
kills address
	gen move %2, {regrel, %1.reg, $1+%1.ind}

pat sti $1==1
with GENREG GENREG
kills address
	gen STR_B %2, {regind, %1}
with  addr_local GENREG
kills address
	gen STR_B %2, {lb_local, %1.ind}
with  addr_external GENREG
kills address
	gen STR_B %2, {absolute, %1.add}
with  regconst GENREG
kills address
	gen STR_B %2, {regrel, %1.reg, %1.ind}
with  regplusreg GENREG
kills address
	gen STR_B %2, {regregrel, %1.reg1, %1.reg2}
with  regminreg GENREG
kills address
	gen STR_B %2, {regminregrel, %1.reg1, %1.reg2}
with  regplusiSreg GENREG
kills address
	gen STR_B %2, {regiSregrel, %1.reg1, %1.S, %1.shift, %1.reg2}
with  regminiSreg GENREG
kills address
	gen STR_B %2, {regminiSregrel, %1.reg1, %1.S, %1.shift, %1.reg2}

with  regplusrSreg GENREG
kills address
uses GENREG
gen move {regS, %1.reg2, %1.S, %1.sreg}, %a
    STR_B %2, {regregrel, %1.reg1, %a}

with  regminrSreg GENREG
kills address
	gen STR_B %2, {regminrSregrel, %1.reg1, %1.S, %1.sreg, %1.reg2}

pat sti $1==2
with GENREG GENREG
kills address
/*uses GENREG
gen move {imS, %2, "LSR", 8}, %a
    SUB %2, %2, {imS, %a, "LSL", 8}
    STR_B %2, {regind, %1}
    STR_B %a, {regrel, %1, 1}
*/
gen STR_B %2, {regind, %1}
    MOV   %2, {imS, %2, "LSR", 8}
    STR_B %2, {regrel, %1, 1}
/*with GENREG fitcon %2.num==0
kills address
gen STR_B %2, {regind, %1}
    STR_B %2, {regrel, %1, 1}
*/
pat sti $1==4
with GENREG GENREG
kills address
	gen move %2, {regind, %1}
with addr_local GENREG
kills address
	gen move %2, {lb_local, %1.ind}
with addr_external GENREG
kills address
	gen move %2, {absolute, %1.add}
with regconst GENREG
kills address
	gen move %2, {regrel, %1.reg, %1.ind}
with  regplusreg GENREG
kills address
	gen move %2, {regregrel, %1.reg1, %1.reg2}
with  regminreg GENREG
kills address
	gen move %2, {regminregrel, %1.reg1, %1.reg2}
with  regplusiSreg GENREG
kills address
	gen move %2, {regiSregrel, %1.reg1, %1.S, %1.shift, %1.reg2}
with  regminiSreg GENREG
kills address
	gen move %2, {regminiSregrel, %1.reg1, %1.S, %1.shift, %1.reg2}
with  regplusrSreg GENREG
kills address
uses GENREG
gen move {regS, %1.reg2, %1.S, %1.sreg}, %a
    STR %2, {regregrel, %1.reg1, %a}
with  regminrSreg GENREG
kills address
	gen move %2, {regminrSregrel, %1.reg1, %1.S, %1.sreg, %1.reg2}

pat sti defined($1) && legal($1)
with GENREG STACK
kills address
uses GENREG={fitcon, $1}
gen	LABEL {label, "1:"}
	SUB_S %a, %a, {fitcon, 4}
	move {st_regregrel, SP, %a}, R11
	move R11, {regregrel, %1, %a}
	BGT {label,"1B"}
	ADD SP, SP, {fitcon, $1}

pat sti defined($1)
with GENREG STACK
kills address
uses GENREG={const4, $1}, GENREG
gen	move %a, %b
	LABEL {label, "1:"}
	SUB_S %a, %a, {fitcon, 4}
	move {st_regregrel, SP, %a}, R11
	move R11, {regregrel, %1, %a}
	BGT {label,"1B"}
	ADD SP, SP, %b

pat sts
with STACK
kills ALL
gen BAL_L {label, ".sts"}

pat sdl
with GENREG GENREG
kills address-absolute
gen 	move %1, {lb_local,$1}
	move %2, {lb_local,$1+4}

pat sde
with GENREG GENREG
kills address
gen	move %1, {absolute, $1}
	move %2, {absolute, $1+4}

pat sdf
with GENREG GENREG GENREG
kills address
gen	move %2, {regrel, %1, $1}
	move %3, {regrel, %1, $1+4}

/************************************************************************
 *									*
 * GROUP III :	Integer Arithmetic					*
 *									*
 ************************************************************************/

pat adi $1==4
with GENREG constant			yields {regconst, %1, %2.num}
with constant GENREG			yields {regconst, %2, %1.num}
with GENREG GENREG			yields {regplusreg, %1, %2}
with GENREG imS				yields {regplusiSreg,%1, %2.S,
							%2.shift, %2.reg}
with imS GENREG 			yields {regplusiSreg,%2, %1.S,
							%1.shift, %1.reg}
with GENREG regS			yields {regplusrSreg,%1, %2.S,
							%2.sreg, %2.reg}
with regS GENREG 			yields {regplusrSreg,%2, %1.S,
							%1.sreg, %1.reg}
with exact addr_local constant		yields {addr_local, %1.ind+%2.num}
with exact constant addr_local 		yields {addr_local, %2.ind+%1.num}
with exact addr_external constant	yields {addr_external, %1.add+%2.num}
with exact constant addr_external	yields {addr_external, %2.add+%1.num}

pat sbi $1==4
with GENREG GENREG			yields {regminreg, %2, %1}
with imS GENREG				yields {regminiSreg,%2,%1.S,
							%1.shift,%1.reg}
with regS GENREG			yields {regminrSreg,%2,%1.S,
							%1.sreg,%1.reg}
with GENREG fitcon
uses GENREG
gen RSB  %a, %1, %2			yields %a
with fitcon GENREG
gen SUB %2, %2, %1			yields %2
with GENREG const4
uses GENREG
gen move %2, %a
    RSB  %1, %1, %a			yields %1
with const4 GENREG
uses GENREG
gen move %1, %a
    SUB  %a, %2, %a			yields %a
with GENREG REGcon
uses GENREG
gen	RSB %a, %1, %2			yields %a
/*with constant GENREG			yields {regconst, %2, 0-%1.num}*/
with exact constant addr_local		yields {addr_local, %2.ind-%1.num}

pat loc mli $1<0 && $2==4		leaving loc 0-$1
						mli 4
						ngi 4

pat loc mli $1==2 && $2==4
with GENREG				yields {imS, %1, "LSL", 1}

pat loc mli $1==4 && $2==4
with GENREG				yields {imS, %1, "LSL", 2}

pat loc mli $1==8 && $2==4
with GENREG				yields {imS, %1, "LSL", 3}

pat loc mli $1==16 && $2==4
with GENREG				yields {imS, %1, "LSL", 4}

pat loc mli $1==32 && $2==4
with GENREG				yields {imS, %1, "LSL", 5}

pat loc mli $1==3 && $2==4
with GENREG				yields {regplusiSreg,%1,"LSL",1,%1}

pat loc mli $1==5 && $2==4
with GENREG				yields {regplusiSreg,%1,"LSL",2,%1}

pat loc mli $1==6 && $2==4
with GENREG
uses GENREG
gen MOV %a, {imS,%1,"LSL",2}
    ADD %a, %a, {imS,%1,"LSL",1}        yields %a

pat loc mli $1==7 && $2==4
with GENREG
uses GENREG
gen RSB %a, %1, {imS, %1, "LSL", 3}	yields %a

pat loc mli $1==9 && $2==4
with GENREG				yields {regplusiSreg,%1,"LSL",3,%1}

pat loc mli $1==10 && $2==4
with GENREG
uses GENREG
gen MOV %a,{imS, %1, "LSL", 1}
    ADD %a, %a, {imS, %1, "LSL", 3}	yields %a

pat loc mli $1==12 && $2==4
with GENREG
uses GENREG
gen move {imS, %1, "LSL", 3}, %a	yields {regplusiSreg,%a,"LSR",1,%a}

pat mli $1==4
with STACK
kills ALL
gen	BAL_L {label, ".mli"}		yields R0

pat loc dvi $1<0 && $2==4		leaving loc 0-$1
						dvi 4

pat dvi $1==4
with STACK
kills ALL
gen	BAL_L {label, ".dvi"}		yields R3

pat rmi $1==4
with STACK
kills ALL
gen	BAL_L {label, ".dvi"}		yields R2

pat ngi $1==4
with GENREG
uses GENREG
gen 	RSB %a, %1, {fitcon, 0}		yields %a

pat sli $1==4
with fitcon GENREG			yields {imS, %2, "LSL", %1.num}
with GENREG GENREG			yields {regS, %2, "LSL", %1}

pat loc sri $1==0 && $2==4
with address+REGcon			yields %1

pat sri $1==4
with fitcon GENREG			yields {imS, %2, "ASR", %1.num}
with GENREG GENREG			yields {regS, %2, "ASR", %1}


/************************************************************************
 *									*
 * GROUP IV :	Unsigned Arithmetic					*
 *									*
 ************************************************************************/

pat adu					leaving adi $1

pat sbu					leaving sbi $1

pat loc mlu $1<11 && $1>0 && $2==4	leaving loc $1
						mli 4

pat mlu $1==4
with STACK
kills ALL
gen	BAL_L {label, ".mlu"}		yields R0

pat loc dvu $1<33 && $1>0 && $2==4	leaving loc $1
						dvi 4

pat dvu $1==4
with STACK
kills ALL
gen	BAL_L {label, ".dvu"}		yields R3

pat rmu $1==4
with STACK
kills ALL
gen	BAL_L {label, ".dvu"}		yields R2

pat slu $1==4
with GENREG GENREG			yields {regS, %2, "LSL", %1}
with const4+fitcon GENREG		yields {imS, %2, "LSL", %1.num}

pat sru $1==4
with GENREG GENREG			yields {regS, %2, "LSR", %1}
with const4+fitcon GENREG		yields {imS, %2, "LSR", %1.num}

/************************************************************************
 *									*
 * GROUP V :	Floating Point Arithmetic 				*
 *									*
 ************************************************************************/

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 4
pat fif $1==8           leaving lor 1 cal ".fif8" asp 4
pat fef $1==4           leaving lor 1 adp 0-4 cal ".fef4"
pat fef $1==8           leaving lor 1 adp 0-4 cal ".fef8"

/************************************************************************
 *									*
 * GROUP VI :	Pointer Arithmetic					*
 *									*
 ************************************************************************/

pat adp
with GENREG				yields {regconst, %1, $1}
with exact addr_local			yields {addr_local, %1.ind+$1}
with exact addr_external		yields {addr_external, %1.add+$1}
with exact regconst			yields {regconst, %1.reg, %1.ind+$1}

pat ads $1==4				leaving adi 4

pat sbs	$1==4				leaving sbi 4

/************************************************************************
 *									*
 * GROUP VII :	Increment/Decrement/Zero				*
 *									*
 ************************************************************************/

pat inc
with GENREG				yields {regconst, %1, 1}
with exact regconst			yields {regconst, %1.reg, %1.ind+1}

pat inl
kills address-absolute
uses GENREG={lb_local,$1}
gen ADD %a,%a,{fitcon,1}
    move %a,{lb_local,$1}

pat ine
kills address
uses GENREG={absolute,$1}
gen ADD %a,%a,{fitcon,1}
    move %a,{absolute,$1}

pat dec
with GENREG				yields {regconst, %1, 0-1}
/*gen SUB %a, %1, {fitcon, 1}*/
with exact regconst			yields {regconst, %1.reg, %1.ind-1}

pat del
kills address-absolute
uses GENREG={lb_local,$1}
gen SUB %a,%a,{fitcon,1}
    move %a,{lb_local,$1}

pat dee
kills address
uses GENREG={absolute,$1}
gen SUB %a,%a,{fitcon,1}
    move %a,{absolute,$1}

pat zrl
kills address-absolute
uses GENREG={fitcon,0}
gen move %a,{lb_local,$1}

pat zre
kills address
uses GENREG={fitcon,0}
gen move %a,{absolute,$1}

pat zrf	leaving zer $1

pat zer $1==4				yields {fitcon,0}

pat zer $1==8				yields {fitcon,0} {fitcon,0}

pat zer $1==12				yields {fitcon,0} {fitcon,0} {fitcon,0}

pat zer defined($1)
with STACK
kills ALL
uses GENREG={fitcon,0},GENREG={const4,$1}
gen LABEL {label, "1:"}
    STMFD {autoid, SP}, {reglist1, %a}
    SUB_S %b,%b,{fitcon,4}
    BNE {label,"1B"}

/************************************************************************
 *									*
 * GROUP VIII :	Convert 						*
 *									*
 ************************************************************************/

/* sign extension short -> integer */
pat loc loc cii $1==2 && $2==4
with GENREG
uses GENREG
gen MOV %a, {imS, %1, "LSL", 16}
    MOV %a, {imS, %a, "ASR", 16}		yields %a

/* sign extension byte -> integer */
pat loc loc cii $1==1 && $2==4
with GENREG
uses GENREG
gen MOV %a, {imS, %1, "LSL", 24}
    MOV %a, {imS, %a, "ASR", 24}		yields %a

pat loc loc cii ($1 > 2)

pat cui
with address +REGcon address + REGcon

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

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

pat loc loc cfi	leaving loc $1 loc $2 cal ".cfi" asp 8+($1-4)

pat loc loc cfu	leaving loc $1 loc $2 cal ".cfu" asp 8+($1-4)

pat loc loc cff	$1==8 && $2==4 leaving cal ".cff4" asp 4

/* this one expects a 4 byte hole on the stack */
pat loc loc cff	$1==4 && $2==8	leaving dup 4 cal ".cff8"

pat ciu
with address +REGcon address + REGcon

pat cuu
with address +REGcon address + REGcon

/************************************************************************
 *									*
 * GROUP IX :	Logical 						*
 *									*
 ************************************************************************/

pat and $1==4
with REGcon GENREG
uses GENREG
gen AND %a, %2, %1			yields %a
with GENREG REGcon
uses GENREG
gen AND %a, %1, %2			yields %a

pat ior $1==4
with REGcon GENREG
uses GENREG
gen ORR %a, %2, %1			yields %a
with GENREG REGcon
uses GENREG
gen ORR %a, %1, %2			yields %a

pat xor $1==4
with REGcon GENREG
uses GENREG
gen EOR %a, %2, %1			yields %a
with GENREG REGcon
uses GENREG
gen EOR %a, %1, %2			yields %a

pat com $1==4
with REGcon
uses GENREG
gen MVN %a,%1				yields %a

pat ror $1==4
with constant GENREG			yields {imS, %2, "ROR", %1.num}
with GENREG GENREG			yields {regS, %2, "ROR", %1}

pat rol $1==4
with constant GENREG			yields {imS, %2, "ROR", 32-%1.num}
with GENREG GENREG
uses GENREG
gen RSB %a, %1, {fitcon,32}		yields {regS, %2, "ROR", %a}

pat and $1>4
with STACK
kills ALL
uses GENREG,GENREG,GENREG,GENREG
gen move {const4,$1}, %b
    move SP, %a
    ADD SP, SP, %b
    LABEL {label, "1:"}
    SUB_S %b, %b, {fitcon, 4}
    move {st_regregrel, SP,%b}, %c
    move {regregrel, %a, %b}, %d
    AND %c, %c, %d
    move %c, {st_regregrel, SP, %b}
    BNE {label, "1B"}

pat ior $1>4
with STACK
kills ALL
uses GENREG,GENREG,GENREG,GENREG
gen move {const4,$1}, %b
    move SP, %a
    ADD SP, SP, %b
    LABEL {label, "1:"}
    SUB_S %b, %b, {fitcon, 4}
    move {st_regregrel, SP,%b}, %c
    move {regregrel, %a, %b}, %d
    ORR %c, %c, %d
    move %c, {st_regregrel, SP, %b}
    BNE {label, "1B"}

pat ior !defined($1)
with STACK
kills ALL
uses GENREG,GENREG,GENREG,GENREG
gen LDMFD {autoid, SP}, {reglist1, %b}
    move SP, %a
    ADD SP, SP, %b
    LABEL {label, "1:"}
    SUB_S %b, %b, {fitcon, 4}
    move {st_regregrel, SP, %b}, %c
    move {regregrel, %a, %b}, %d
    ORR %c, %c, %d
    move %c, {st_regregrel, SP, %b}
    BNE {label, "1B"}


pat xor $1>4
with STACK
kills ALL
uses GENREG,GENREG,GENREG,GENREG
gen move {const4,$1}, %b
    move SP, %a
    ADD SP, SP, %b
    LABEL {label, "1:"}
    SUB_S %b, %b, {fitcon, 4}
    move {st_regregrel, SP,%b}, %c
    move {regregrel, %a, %b}, %d
    EOR %c, %c, %d
    move %c, {st_regregrel, SP, %b}
    BNE {label, "1B"}

pat com $1>4
with STACK
kills ALL
uses GENREG,GENREG,GENREG
gen move {const4,$1}, %b
    LABEL {label, "1:"}
    SUB_S %b, %b, {fitcon, 4}
    move {st_regregrel, SP, %b}, %c
    MVN %c, %c
    move %c, {st_regregrel, SP, %b}
    BNE {label, "1B"}

/************************************************************************
 *									*
 * GROUP X:	Sets  							*
 *									*
 ************************************************************************/

pat loc loc inn !defined($3)		leaving loc $1 inn $2

pat loc inn $2==4 && $1>=0 && $1<32
with GENREG
uses GENREG={fitcon,1},GENREG
gen AND %b, %1, {imS,%a,"LSL",$1}	yields %b

pat loc inn $2==4 && $1<0
with GENREG
gen move {fitcon,0}, %1			yields %1

pat loc inn $2==4 && $1>31		leaving loc 2 trp

pat loc inn !defined($2)		leaving inn $1

pat inn defined($1)
with GENREG STACK
uses GENREG={fitcon,1}, GENREG, GENREG
gen AND %b, %1, {fitcon, 31}
    move {regS, %a, "LSL", %b}, %b
    move {imS, %1, "LSR", 5}, %1
    move {st_regiSregrel, SP, "LSL", 2, %1}, %c
    AND_S %b, %b, %c
    MOV_NE %b, {fitcon, 1}
    ADD SP, SP, {const4, $1}            yields %b

pat inn !defined($1)
with GENREG GENREG STACK
uses GENREG={fitcon,1}, GENREG, GENREG
gen AND %b, %2, {fitcon, 31}
    move {regS, %a, "LSL", %b}, %b
    move {imS, %2, "LSR", 5}, %2
    move {st_regiSregrel, SP, "LSL", 2, %2}, %c
    AND_S %b, %b, %c
    MOV_NE %b, {fitcon, 1}
    ADD SP, SP, %1                      yields %b

pat loc set !defined($2)		leaving set $1

pat set $1==4
with const4
uses GENREG={fitcon,1} 			yields {imS,%a,"LSL",%1.num}
with GENREG
uses GENREG={fitcon,1}			yields {regS,%a,"LSL",%1}

pat set $1>4
with GENREG STACK
uses GENREG={fitcon,1}, GENREG={fitcon,0}, GENREG={const4,$1}
gen LABEL {label, "2:"}
    STMFD {autoid, SP}, {reglist1, %b}
    SUB_S %c, %c, {fitcon,4}
    BGT {label, "2B"}
    CMP %1, {fitcon, 0}
    BMI {label, "1F"}
    AND %b, %1, {fitcon, 31}
    move {regS, %a, "LSL", %b}, %b
    move {imS, %1, "LSR", 5}, %1
    move %b, {st_regiSregrel, SP, "LSL", 2, %1}
    LABEL {label, "1:"}

pat set !defined($1)
with STACK
kills ALL
uses GENREG={fitcon,1}, GENREG={fitcon,0}, GENREG, GENREG
gen LDMFD {autoid, SP}, {reglist1, %c}
    LDMFD {autoid, SP}, {reglist1, %d}
    LABEL {label, "2:"}
    STMFD {autoid, SP}, {reglist1, %b}
    SUB_S %c, %c, {fitcon,4}
    BGT {label, "2B"}
    CMP %d, {fitcon, 0}
    BMI {label, "1F"}
    AND %b, %d, {fitcon, 31}
    move {regS, %a, "LSL", %b}, %b
    move {imS, %d, "LSR", 5}, %d
    move %b, {st_regiSregrel, SP, "LSL", 2, %d}
    LABEL {label, "1:"}

/************************************************************************
 *									*
 * GROUP XI :	Array Instructions					*
 *									*
 ************************************************************************/

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

pat lae aar $2==4 && rom($1,3)==1 && rom($1,1)>0 && legal(rom($1,1))
with GENREG
uses GENREG
gen SUB %a,%1,{fitcon,rom($1,1)}		yields %a
						leaving adi 4
with exact regconst				yields {regconst, %1.reg,
							%1.ind-rom($1,1)}
						leaving adi 4

pat lae aar $2==4 && rom($1,3)==1 && rom($1,1)!=0
with GENREG
uses GENREG={const4, 0-rom($1,1)}
gen ADD %a,%1,%a				yields %a
						leaving adi 4
with exact regconst				yields {regconst, %1.reg,
							%1.ind-rom($1,1)}
						leaving adi 4

pat lae aar $2==4 && rom($1,3)==4 && rom($1,1)==0
with GENREG					yields {imS, %1,"LSL",  2}
						leaving adi 4

pat lae aar $2==4 && rom($1,3)==4 && rom($1,1)>0 && legal(rom($1,1))
with GENREG
uses GENREG
gen SUB %a,%1,{fitcon, rom($1,1)}		yields {imS, %a,"LSL", 2}
						leaving adi 4

pat lae aar $2==4 && rom($1,3)==4 && rom($1,1)!=0
with GENREG
uses GENREG={const4, 0-rom($1,1)}
gen ADD %a,%1,%a				yields {imS, %a,"LSL", 2}
						leaving adi 4

pat lae aar $2==4 && rom($1,1)==0
						leaving loc rom($1,3)
							mli 4 adi 4

pat lae aar $2==4 && rom($1,1)>0 && legal(rom($1,1))
with GENREG
uses GENREG
gen SUB %a,%1,{fitcon,rom($1,1)}		yields %a
						leaving loc rom($1,3)
							mli 4 adi 4

pat lae aar $2==4 && rom($1,1)!=0
with GENREG
uses GENREG={const4, 0-rom($1,1)}
gen ADD %a,%1,%a				yields %a
						leaving loc rom($1,3)
							mli 4 adi 4

pat aar $1==4
with GENREG GENREG
uses GENREG
gen move {regind, %1}, %a
    SUB %2, %2, %a				yields %2 {regrel, %1, 8}
						leaving mli 4 adi 4

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

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

pat loc aar !defined($2)			leaving aar $1

pat lae loc sar !defined($3) && $2==4 && defined(rom($1,3))
						leaving lae $1 aar 4
							sti rom($1,3)

pat lae loc lar !defined($3) && $2==4 && defined(rom($1,3))
						leaving lae $1 aar 4
							loi rom($1,3)

/* next two: dynamic arrays in modula2 - not tested */

pat lal sar $2==4 leaving lal $1 aar 4 lal $1 adp 8 loi 4 sts

pat lal lar $2==4 leaving lal $1 aar 4 lal $1 adp 8 loi 4 los

/************************************************************************
 *									*
 * GROUP XII :	Compare Instructions					*
 *									*
 ************************************************************************/

pat cmi
with GENREG REGcon
uses reusing %1, GENREG=%1
gen RSB_S %a, %1, %2				yields %a
with REGcon GENREG
uses reusing %2, GENREG=%2
gen SUB_S %a, %2, %1				yields %a

pat cmu $1==4
with GENREG REGcon
uses GENREG
gen CMP %1, %2
    MOV_HI %a, {fitcon, 0-1}
    MOV_LS %a, {fitcon, 1}
    MOV_EQ %a, {fitcon, 0}			yields %a
with REGcon GENREG
uses GENREG
gen CMP %2, %1
    MOV_HI %a, {fitcon, 1}
    MOV_LS %a, {fitcon, 0-1}
    MOV_EQ %a, {fitcon, 0}			yields %a

pat cmp						leaving cmu 4

pat cmf $1==4	leaving cal ".cmf4" asp 8 lfr 4
pat cmf $1==8	leaving cal ".cmf8" asp 16 lfr 4

pat loc cms !defined($2)			leaving cms $1

pat cms $1==4
with GENREG REGcon
gen EOR_S %1, %1, %2				yields %1
with REGcon GENREG
gen EOR_S %2, %2, %1				yields %2

pat cms $1!=4
with STACK
kills ALL
uses GENREG = {const4, $1}, GENREG, GENREG, GENREG, GENREG
gen move %a, %e
    ADD %b, %a, SP
    LABEL {label, "1:"}
    SUB_S %a, %a, {fitcon, 4}
    BLT {label, "2F"}
    move {st_regregrel, SP, %a}, %c
    move {regregrel, %b, %a}, %d
    EOR_S %c, %c, %d
    BEQ {label, "1B"}
    LABEL {label, "2:"}
    ADD SP, %b, %e				yields %c

pat cms !defined($1)
with GENREG STACK
uses GENREG, GENREG, GENREG, GENREG
gen move %1, %d
    ADD %a, %1, SP
    LABEL {label, "1:"}
    SUB_S %1, %1, {fitcon, 4}
    BLT {label, "2F"}
    move {st_regregrel, SP, %1}, %b
    move {regregrel, %a, %1}, %c
    EOR_S %b, %b, %c
    BEQ {label, "1B"}
    LABEL {label, "2:"}
    ADD SP, %a, %d				yields %b

pat tlt
with GENREG
uses reusing %1, GENREG=%1
gen test %1
    MOV_LT %a, {fitcon,1}
    MOV_GE %a, {fitcon,0}			yields %a

pat tle
with  GENREG
uses reusing %1, GENREG=%1
gen test %1
    MOV_LE %a, {fitcon,1}
    MOV_GT %a, {fitcon,0}			yields %a

pat teq
with GENREG
uses reusing %1, GENREG=%1
gen test %1
    MOV_EQ %a, {fitcon,1}
    MOV_NE %a, {fitcon,0}			yields %a

pat tne
with  GENREG
uses reusing %1, GENREG=%1
gen test %1
    MOV_NE %a, {fitcon,1}
    MOV_EQ %a, {fitcon,0}			yields %a

pat tge
with  GENREG
uses reusing %1, GENREG=%1
gen test %1
    MOV_GE %a, {fitcon,1}
    MOV_LT %a, {fitcon,0}			yields %a

pat tgt
with GENREG
uses reusing %1, GENREG=%1
gen test %1
    MOV_GT %a, {fitcon,1}
    MOV_LE %a, {fitcon,0}			yields %a

/************************************************************************
 *									*
 * GROUP XIII :	Branch Instructions					*
 *									*
 ************************************************************************/

pat bra
with STACK
kills ALL
	gen BAL {label, $1}

pat bne
with REGcon GENREG STACK
	gen CMP %2, %1
	    BNE {label, $1}
with GENREG REGcon STACK
	gen CMP %1, %2
	    BNE {label, $1}

pat beq
with REGcon GENREG STACK
	gen CMP %2, %1
	    BEQ {label, $1}
with GENREG REGcon STACK
	gen CMP %1, %2
	    BEQ {label, $1}

pat blt
with REGcon GENREG STACK
	gen CMP %2, %1
	    BLT {label, $1}

pat ble
with REGcon GENREG STACK
	gen CMP %2, %1
	    BLE {label, $1}

pat bgt
with REGcon GENREG STACK
	gen CMP %2, %1
	    BGT {label, $1}

pat bge
with REGcon GENREG STACK
	gen CMP %2, %1
	    BGE {label, $1}

pat zlt
with GENREG STACK
gen test %1
    BLT {label, $1}

pat zle
with GENREG STACK
gen test %1
    BLE {label, $1}

pat zeq
with GENREG STACK
gen test %1
    BEQ {label, $1}

pat zne
with GENREG STACK
gen test %1
    BNE {label, $1}

pat zge
with GENREG STACK
gen test %1
    BGE {label, $1}

pat zgt
with  GENREG STACK
gen test %1
    BGT {label, $1}

/************************************************************************
 *									*
 * GROUP XIV :	Procedure Call						*
 *									*
 ************************************************************************/

pat cal
with STACK
kills ALL
gen BAL_L {label, $1}

pat cai
with GENREG STACK
kills ALL
gen /* the trick is to set up R14 properly */
    ADR LR, {label, "1F"}
    MOV PC, %1
    LABEL {label, "1:"}

pat lfr $1==4				yields R0

pat lfr $1==8				yields R1 R0

pat lfr $1==12				yields R2 R1 R0

pat ret $1==0
with STACK
kills ALL
gen return
    MOV SP, LB
    LDMFD {autoid, SP}, {lb_pc_reglist2, LB, PC}

pat ret $1==4
with address STACK
kills ALL
gen move %1, R0
    return
    move LB, SP
    LDMFD {autoid, SP}, {lb_pc_reglist2, LB, PC}
with REGcon STACK
kills ALL
gen move %1, R0
    return
    move LB, SP
    LDMFD {autoid, SP}, {lb_pc_reglist2, LB, PC}

pat ret $1==8
with REGcon REGcon STACK
kills ALL
gen move %1, R0
    move %2, R1
    return
    move LB, SP
    LDMFD {autoid, SP}, {lb_pc_reglist2, LB, PC}

pat ret $1==12
with REGcon REGcon REGcon STACK
kills ALL
gen move %1, R0
    move %2, R1
    move %3, R2
    return
    move LB, SP
    LDMFD {autoid, SP}, {lb_pc_reglist2, LB, PC}


/************************************************************************
 *									*
 * GROUP XV :	Miscellaneous						*
 *									*
 ************************************************************************/

pat asp legal($1)
with STACK
kills ALL
gen ADD SP, SP, {fitcon, $1}

pat asp
with STACK
kills ALL
uses GENREG={const4, $1}
gen ADD SP, SP, %a

pat ass $1==4
with REGcon STACK
gen ADD SP, SP, %1

pat blm $1==0
with address+REGcon address+REGcon

pat blm $1==1
with GENREG GENREG
kills address
uses GENREG
gen LDR_B %a, {regind, %2}
    STR_B %a, {regind, %1}

pat blm $1==4
with GENREG GENREG
kills address
uses GENREG
gen move {regind, %2}, %a
    move %a, {regind, %1}

pat blm $1>4
with GENREG GENREG
kills address
uses GENREG, GENREG={const4, $1-4}
gen LABEL {label, "1:"}
    move {regregrel, %2, %b}, %a
    move %a, {regregrel, %1, %b}
    SUB_S %b, %b, {fitcon, 4}
    BGE {label,"1B"}

pat bls $1==4
with GENREG GENREG GENREG
kills address
uses GENREG
gen LABEL {label, "1:"}
    SUB_S %1, %1, {fitcon, 4}
    move {regregrel, %3, %1}, %a
    move %a, {regregrel, %2, %1}
    BGT {label,"1B"}

pat csa $1==4
with STACK
kills ALL
gen BAL_L {label, "_Csa"}
    move R2, PC

pat csb $1==4
with STACK
kills ALL
gen BAL_L {label, "_Csb"}
    move R3, PC

pat dch	leaving loi 4

pat dup $1==4
with address+REGcon			yields %1 %1

pat dup $1==8
with address+REGcon address+REGcon	yields %2 %1 %2 %1

pat dup $1>8
with STACK
kills ALL
uses GENREG={const4,$1}, GENREG
gen LABEL {label, "1:"}
    move {st_regrel, SP, $1-4}, %b
    STMFD {autoid, SP}, {reglist1, %b}
    SUB_S %a, %a, {fitcon, 4}
    BGT {label, "1B"}

pat dus
with GENREG STACK
uses GENREG, GENREG
gen SUB %b, %1, {fitcon, 4}
    LABEL {label, "1:"}
    move {st_regregrel, SP, %b}, %a
    STMFD {autoid, SP}, {reglist1, %a}
    SUB_S %1, %1, {fitcon, 4}
    BGT {label, "1B"}

pat exg $1==4
with address+REGcon address+REGcon		yields %1 %2

pat exg $1==8
with address+REGcon address+REGcon
     address+REGcon address+REGcon		yields %2 %1 %4 %3

pat exg $1>8
with STACK
kills ALL
uses GENREG, GENREG, GENREG={const4, $1-4}, GENREG, GENREG={const4, $1}
gen ADD %d, SP, %e
    LABEL {label, "1:"}
    move {st_regregrel, SP,%c}, %a
    move {regregrel,%d,%c}, %b
    move %a, {regregrel,%d,%c}
    move %b, {st_regregrel, SP,%c}
    SUB_S %c, %c, {fitcon, 4}
    BGE {label, "1B"}

pat fil
uses GENREG
gen move {addr_external,$1}, %a
    move %a, {addr_external, "_Filna"}

pat gto        /* this code does NOT restore registers */
uses GENREG,GENREG,GENREG,GENREG
gen move {addr_external, $1}, %d
    move {regind, %d}, %a
    move {regrel, %d, 4}, %b
    move {regrel, %d, 8}, %c
    MOV  LB, %c
    MOV  SP, %b
    MOV  PC, %a

pat lin
kills address
uses GENREG={const4,$1}
gen move %a,{addr_external,"_Lineno"}

pat lni
kills address
uses GENREG
gen move {addr_external,"_Lineno"}, %a
    LDR %a, {regind, %a}
    ADD %a,%a,{fitcon,1}
    move %a,{addr_external,"_Lineno"}

pat lor $1==0				yields LB

pat lor $1==1
with STACK
kills ALL				yields SP

pat lor $1==2				yields {absolute, "_RegHp"}

pat lpb					leaving adp 8

pat nop
kills ALL
gen MOV_NV R0,R0

pat rck
with GENREG REGcon  STACK 
uses GENREG,GENREG
gen move {regind, %1}, %a
    /* for some reason, the code generator expects the value
     * to be checked on top of the stack after checking, while
     * in fact it is held in %2. This causes mayhem later on, and
     * the following two lines rectify this.
     */
    move %2,%b
    STMFD {autoid, SP}, {reglist1, %b}
    CMP %a, %2
    BGT {label, "_RckTrap"}
    move {regrel, %1, 4}, %a
    CMP %a, %2
    BLT {label, "_RckTrap"}

pat lim
with STACK
kills ALL
uses GENREG
gen move {addr_external, "_IgnoreMask"}, %a
    STMFD {autoid, SP}, {reglist1, %a}

pat mon
with STACK
kills ALL
gen BAL_L {label, "_EmMon"}

pat rtt
            leaving ret 0

pat sig
with STACK
kills ALL
uses GENREG,GENREG
gen move {addr_external, "_TrpReg"}, %a
    LDR %a, {regind, %a}
    LDMFD {autoid, SP}, {reglist1, %b}
    move %b, {addr_external, "_TrpReg"}
    STMFD {autoid, SP}, {reglist1, %a}

pat sim
with STACK
kills ALL
uses GENREG
gen LDMFD {autoid, SP}, {reglist1, %a}
    move %a, {addr_external, "_IgnoreMask"}

pat trp
with STACK
kills ALL
gen BAL_L {label, "_EmTrp"}

pat str $1==0
with address
gen move %1, LB
with REGcon
gen move %1, LB

pat str $1==1
with address
gen MOV SP, %1
with REGcon
gen MOV SP, %1

pat str $1==2
with GENREG
gen move %1, {absolute, "_RegHp"}

/***********************************************************************/

/* code for *p++ and *p-- (integers)*/
pat lol dup adp stl loi $1==$4 && $2==4 && $5==4
kills GENREG
uses GENREG, GENREG
gen move {lb_local, $1}, %a
    LDR %b, {regrelpi, %a, $5}
    STR %a, {lb_local, $1}		yields %b

pat lol dup adp stl sti $1==$4 && $2==4 && $5==4
with GENREG
kills GENREG
uses GENREG
gen move {lb_local,$1}, %a
    STR %1, {regrelpi, %a, $5}
    STR %a, {lb_local, $1}

/* code for *p++ and *p-- (bytes)*/
pat lol dup adp stl loi $1==$4 && $2==4 && $5==1
kills GENREG
uses GENREG, GENREG
gen move {lb_local, $1}, %a
    LDR_B %b, {regrelpi, %a, $5}
    STR %a, {lb_local, $1}		yields %b

pat lol dup adp stl sti $1==$4 && $2==4 && $5==1
with GENREG
kills GENREG
uses GENREG
gen move {lb_local,$1}, %a
    STR_B %1, {regrelpi, %a, $5}
    STR %a, {lb_local, $1}

/* code for *pp->p++ and *pp->p-- (integers)*/
pat lil dup adp sil loi $1==$4 && $2==4 && $5==4
kills GENREG
uses GENREG, GENREG, GENREG
gen move {lb_local, $1}, %a
    LDR %b, {regind, %a}
    ADD %c, %b, {fitcon, $5}
    STR %c, {regind, %a}
    LDR %c, {regind, %b}		yields %c

pat lil dup adp sil sti $1==$4 && $2==4 && $5==4
with GENREG
kills GENREG
uses GENREG, GENREG, GENREG
gen move {lb_local, $1}, %a
    LDR %b, {regind, %a}
    ADD %c, %b, {fitcon, $5}
    STR %c, {regind, %a}
    STR %1, {regind, %b}

/* code for *pp->p++ and *pp->p-- (bytes)*/
pat lil dup adp sil loi $1==$4 && $2==4 && $5==1
kills GENREG
uses GENREG, GENREG, GENREG
gen move {lb_local, $1}, %a
    LDR %b, {regind, %a}
    ADD %c, %b, {fitcon, $5}
    STR %c, {regind, %a}
    LDR_B %c, {regind, %b}		yields %c

pat lil dup adp sil sti $1==$4 && $2==4 && $5==1
with GENREG
kills GENREG
uses GENREG, GENREG, GENREG
gen move {lb_local, $1}, %a
    LDR %b, {regind, %a}
    ADD %c, %b, {fitcon, $5}
    STR %c, {regind, %a}
    STR_B %1, {regind, %b}


/* global array access of the form x[y-1] */

pat lol loc mli loc sbi $2==$4 && $3==4 && $5==4
    leaving lol $1 dec 4 loc $2 mli 4

/* x[i] = y with large array elements */

pat lae loi lae lol loc mli ads sti $2==$8 && $2 > 4
    leaving lae $1 lae $3 lol $4 loc $5 mli $6 ads $7 blm $8
pat lae loi lae lol loc mlu ads sti $2==$8 && $2 > 4
    leaving lae $1 lae $3 lol $4 loc $5 mlu $6 ads $7 blm $8

/* prevent double push/pull of $1 */

pat lae lol loc mli ads
    leaving lol $2 loc $3 mli $4 lae $1 ads $5
pat lae lol loc mlu ads
    leaving lol $2 loc $3 mlu $4 lae $1 ads $5

pat lae lol loc mli ads lol loc mli ads $5==$9 && $4==$8
    leaving lol $2 loc $3 mli $4 lol $6 loc $7 mli $8 ads $5 lae $1 ads $9
pat lae lol loc mlu ads lol loc mlu ads $5==$9 && $4==$8
    leaving lol $2 loc $3 mlu $4 lol $6 loc $7 mlu $8 ads $5 lae $1 ads $9

pat lae lol adp loi loc mli ads
    leaving lol $2 adp $3 loi $4 loc $5 mli $6 lae $1 ads $7
pat lae lol adp loi loc mlu ads
    leaving lol $2 adp $3 loi $4 loc $5 mlu $6 lae $1 ads $7

/*
pat lae loi lae lol adp loi loc mli ads sti $2==$10 && $2 > 4
    leaving lae $1 lae $3 lol $4 adp $5 loi $6 loc $7 mli $8 ads $9 blm $2
pat lae loi lae lol adp loi loc mlu ads sti $2==$10 && $2 > 4
    leaving lae $1 lae $3 lol $4 adp $5 loi $6 loc $7 mlu $8 ads $9 blm $2
*/
